From 2fb4807f73c670d5112f8f425fba0cde527aa546 Mon Sep 17 00:00:00 2001 From: NeoCoderMatrix86 <40752681+NeoCoderMatrix86@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:45:41 +0100 Subject: [PATCH 01/30] Renamed tracklist component --- AudioCuesheetEditor/AudioCuesheetEditor.csproj | 8 ++++---- AudioCuesheetEditor/Pages/Index.razor | 2 +- AudioCuesheetEditor/Pages/ViewModeImport.razor | 2 +- AudioCuesheetEditor/Pages/ViewModeRecord.razor | 2 +- .../Localization/{TracksTable => TrackList}/de.json | 0 .../Localization/{TracksTable => TrackList}/en.json | 0 .../Shared/{TracksTable.razor => TrackList.razor} | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) rename AudioCuesheetEditor/Resources/Localization/{TracksTable => TrackList}/de.json (100%) rename AudioCuesheetEditor/Resources/Localization/{TracksTable => TrackList}/en.json (100%) rename AudioCuesheetEditor/Shared/{TracksTable.razor => TrackList.razor} (99%) diff --git a/AudioCuesheetEditor/AudioCuesheetEditor.csproj b/AudioCuesheetEditor/AudioCuesheetEditor.csproj index ff8fb902..520f5836 100644 --- a/AudioCuesheetEditor/AudioCuesheetEditor.csproj +++ b/AudioCuesheetEditor/AudioCuesheetEditor.csproj @@ -41,8 +41,8 @@ - - + + @@ -88,8 +88,8 @@ - - + + diff --git a/AudioCuesheetEditor/Pages/Index.razor b/AudioCuesheetEditor/Pages/Index.razor index b9d76fc5..5630bb5c 100644 --- a/AudioCuesheetEditor/Pages/Index.razor +++ b/AudioCuesheetEditor/Pages/Index.razor @@ -59,7 +59,7 @@ along with Foobar. If not, see @_localizer["Tracks"] - + diff --git a/AudioCuesheetEditor/Pages/ViewModeImport.razor b/AudioCuesheetEditor/Pages/ViewModeImport.razor index 05cf22ba..8f302f3c 100644 --- a/AudioCuesheetEditor/Pages/ViewModeImport.razor +++ b/AudioCuesheetEditor/Pages/ViewModeImport.razor @@ -135,7 +135,7 @@ along with Foobar. If not, see @_localizer["Tracks"] - + diff --git a/AudioCuesheetEditor/Pages/ViewModeRecord.razor b/AudioCuesheetEditor/Pages/ViewModeRecord.razor index b68a38fd..100ac4fb 100644 --- a/AudioCuesheetEditor/Pages/ViewModeRecord.razor +++ b/AudioCuesheetEditor/Pages/ViewModeRecord.razor @@ -108,7 +108,7 @@ along with Foobar. If not, see @_localizer["Tracks"] - + diff --git a/AudioCuesheetEditor/Resources/Localization/TracksTable/de.json b/AudioCuesheetEditor/Resources/Localization/TrackList/de.json similarity index 100% rename from AudioCuesheetEditor/Resources/Localization/TracksTable/de.json rename to AudioCuesheetEditor/Resources/Localization/TrackList/de.json diff --git a/AudioCuesheetEditor/Resources/Localization/TracksTable/en.json b/AudioCuesheetEditor/Resources/Localization/TrackList/en.json similarity index 100% rename from AudioCuesheetEditor/Resources/Localization/TracksTable/en.json rename to AudioCuesheetEditor/Resources/Localization/TrackList/en.json diff --git a/AudioCuesheetEditor/Shared/TracksTable.razor b/AudioCuesheetEditor/Shared/TrackList.razor similarity index 99% rename from AudioCuesheetEditor/Shared/TracksTable.razor rename to AudioCuesheetEditor/Shared/TrackList.razor index 61947058..c3fd2e20 100644 --- a/AudioCuesheetEditor/Shared/TracksTable.razor +++ b/AudioCuesheetEditor/Shared/TrackList.razor @@ -18,11 +18,11 @@ along with Foobar. If not, see @implements IDisposable -@inject ITextLocalizer _localizer +@inject ITextLocalizer _localizer @inject SessionStateContainer _sessionStateContainer @inject ILocalStorageOptionsProvider _localStorageOptionsProvider @inject TraceChangeManager _traceChangeManager -@inject ILogger _logger +@inject ILogger _logger @inject ITextLocalizerService _localizationService @inject MusicBrainzDataProvider _musicBrainzDataProvider @inject ITextLocalizer _validationMessageLocalizer From 584dfa18a6bf554ceed79109924bb3dde8644ae9 Mon Sep 17 00:00:00 2001 From: NeoCoderMatrix86 <40752681+NeoCoderMatrix86@users.noreply.github.com> Date: Mon, 11 Nov 2024 11:03:33 +0100 Subject: [PATCH 02/30] Update Cuesheet.cs --- AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs index 755f4d14..68ef6766 100644 --- a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs +++ b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs @@ -333,6 +333,7 @@ public void RemoveTracks(IReadOnlyCollection tracksToRemove) tracks.ForEach(x => x.IsLinkedToPreviousTrackChanged += Track_IsLinkedToPreviousTrackChanged); RecalculateLastTrackEnd(); OnTraceablePropertyChanged(previousValue, nameof(Tracks)); + //TODO: Doesn't fire TrackRemoved (with a list of removed tracks) } public Boolean MoveTrackPossible(Track track, MoveDirection moveDirection) From add2c80f9b30c52fede40b4e09502492e20e8435 Mon Sep 17 00:00:00 2001 From: NeoCoderMatrix86 <40752681+NeoCoderMatrix86@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:39:02 +0100 Subject: [PATCH 03/30] More components for tracklist --- AudioCuesheetEditor/Shared/TrackList.razor | 805 ------------------ .../Shared/TrackList/TrackList.razor | 489 +++++++++++ .../Shared/TrackList/TrackListItem.razor | 399 +++++++++ .../Shared/TrackList/TrackSelection.razor | 59 ++ AudioCuesheetEditor/_Imports.razor | 1 + 5 files changed, 948 insertions(+), 805 deletions(-) delete mode 100644 AudioCuesheetEditor/Shared/TrackList.razor create mode 100644 AudioCuesheetEditor/Shared/TrackList/TrackList.razor create mode 100644 AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor create mode 100644 AudioCuesheetEditor/Shared/TrackList/TrackSelection.razor diff --git a/AudioCuesheetEditor/Shared/TrackList.razor b/AudioCuesheetEditor/Shared/TrackList.razor deleted file mode 100644 index c3fd2e20..00000000 --- a/AudioCuesheetEditor/Shared/TrackList.razor +++ /dev/null @@ -1,805 +0,0 @@ - - -@implements IDisposable - -@inject ITextLocalizer _localizer -@inject SessionStateContainer _sessionStateContainer -@inject ILocalStorageOptionsProvider _localStorageOptionsProvider -@inject TraceChangeManager _traceChangeManager -@inject ILogger _logger -@inject ITextLocalizerService _localizationService -@inject MusicBrainzDataProvider _musicBrainzDataProvider -@inject ITextLocalizer _validationMessageLocalizer -@inject ApplicationOptionsTimeSpanParser _applicationOptionsTimeSpanParser - - - @if (_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull) - { - var validationResult = Cuesheet?.Validate(x => x.Tracks); - - - @_localizer["Validation errors"] - - @if (validationResult?.ValidationMessages != null) - { - @foreach(var message in validationResult.ValidationMessages) - { - @message.GetMessageLocalized(_validationMessageLocalizer) - } - } - - - - - - - - - - - @_localizer["Add new track"] - - - - - - @if (TrackSelectionVisible == false) - { - - - - - - - - @_localizer["Display selection of tracks"] - - - - } - else - { - - - - - - - - @_localizer["Hide selection of tracks"] - - - - } - - - - - - - - - - @_localizer["Edit selected tracks"] - - - - - - - - - - @_localizer["Delete selected tracks"] - - - - - - - - - - @_localizer["Delete all tracks"] - - - - - - - } - - - - - @if ((_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull) && (TrackSelectionVisible)) - { - - - @if (Cuesheet?.Tracks.Count > 0) - { - - - - } - @_localizer["Selection"] - - - } - @switch (_sessionStateContainer.CurrentViewMode) - { - case ViewMode.ViewModeFull: - case ViewMode.ViewModeImport: - @_localizer["Controls"] - break; - case ViewMode.ViewModeRecord: - @_localizer["Controls"] - break; - } - # - @_localizer["Artist"] - @_localizer["Title"] - @_localizer["Begin"] - @_localizer["End"] - @_localizer["Length"] - - - - @if (Cuesheet != null) - { - - @if ((track != Cuesheet?.Tracks.FirstOrDefault()) && (_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull)) - { - - - @if (track.IsLinkedToPreviousTrack) - { - - - - - @_localizer["Unlink this track from previous track"] - - } - else - { - - - - - @_localizer["Link this track with previous track"] - - } - - - } - - @if (TrackSelectionVisible) - { - - - - - - } - @switch (_sessionStateContainer.CurrentViewMode) - { - case ViewMode.ViewModeRecord: - - - - - - - - @track.Position - break; - case ViewMode.ViewModeFull: - case ViewMode.ViewModeImport: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - break; - } - - - - - @if (context.Item.Disambiguation != null) - { - @String.Format("{0} ({1})", context.Text, context.Item.Disambiguation) - } - else - { - @context.Text - } - - - - - - - - - @if (context.Item.Disambiguation != null) - { - @String.Format("{0} ({1})", context.Text, context.Item.Disambiguation) - } - else - { - @context.Text - } - - - - - @switch (_sessionStateContainer.CurrentViewMode) - { - case ViewMode.ViewModeRecord: - @track.Begin - @track.End - @track.Length - break; - case ViewMode.ViewModeFull: - case ViewMode.ViewModeImport: - - - @if (Cuesheet?.GetSectionAtTrack(track) != null) - { - - - - - - - - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - break; - } - - - } - - - - - - - -@code { - ModalDialog? modalDialog; - EditTrackModal? modalTrackEdit; - List selectedTracks = new(); - IEnumerable? autocompleteTrackArtists; - IEnumerable? autocompleteTrackTitles; - Boolean _trackSelectionVisible = false; - //Saved locally because of performance (do not load everytime something is edited) - ApplicationOptions? applicationOptions; - Validations? validations; - Boolean revalidate = false; - List TracksAttachedToValidateablePropertyChanged = new(); - - [Parameter] - public AudioPlayer? AudioPlayer { get; set; } - - public Cuesheet? Cuesheet - { - get - { - Cuesheet? cuesheet; - switch (_sessionStateContainer.CurrentViewMode) - { - case ViewMode.ViewModeImport: - cuesheet = _sessionStateContainer.ImportCuesheet; - break; - default: - cuesheet = _sessionStateContainer.Cuesheet; - break; - } - return cuesheet; - } - } - - public Boolean TrackSelectionVisible - { - get => _trackSelectionVisible; - set - { - _trackSelectionVisible = value; - selectedTracks = new(); - } - } - - public void Dispose() - { - _localizationService.LocalizationChanged -= LocalizationService_LocalizationChanged; - _localStorageOptionsProvider.OptionSaved -= LocalStorageOptionsProvider_OptionSaved; - _sessionStateContainer.CuesheetChanged -= SessionStateContainer_CuesheetChanged; - _sessionStateContainer.ImportCuesheetChanged -= SessionStateContainer_ImportCuesheetChanged; - _traceChangeManager.UndoDone -= TraceChangeManager_UndoDone; - _traceChangeManager.RedoDone -= TraceChangeManager_RedoDone; - _sessionStateContainer.Cuesheet.TrackRemoved -= Cuesheet_TrackRemoved; - _sessionStateContainer.Cuesheet.TrackAdded -= Cuesheet_TrackAdded; - DetachTrackFromValidateablePropertyChanged(); - DetachCuesheetFromSplitPointsAddedRemoved(); - } - - protected override async Task OnInitializedAsync() - { - _logger.LogDebug("OnInitializedAsync"); - - _localizationService.LocalizationChanged += LocalizationService_LocalizationChanged; - - applicationOptions = await _localStorageOptionsProvider.GetOptions(); - _localStorageOptionsProvider.OptionSaved += LocalStorageOptionsProvider_OptionSaved; - - _sessionStateContainer.CuesheetChanged += SessionStateContainer_CuesheetChanged; - _sessionStateContainer.ImportCuesheetChanged += SessionStateContainer_ImportCuesheetChanged; - - _traceChangeManager.UndoDone += TraceChangeManager_UndoDone; - _traceChangeManager.RedoDone += TraceChangeManager_RedoDone; - - _sessionStateContainer.Cuesheet.TrackAdded += Cuesheet_TrackAdded; - _sessionStateContainer.Cuesheet.TrackRemoved += Cuesheet_TrackRemoved; - - AttachTracksToValidateablePropertyChanged(); - AttachCuesheetToSplitPointsAddedRemoved(); - } - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - await base.OnAfterRenderAsync(firstRender); - _logger.LogDebug("OnAfterRenderAsync({firstRender})", firstRender); - if ((revalidate) && (validations != null)) - { - await validations.ValidateAll(); - revalidate = false; - } - } - - Task OnAddTrackClicked() - { - var newTrack = new Track(); - Cuesheet?.AddTrack(newTrack, applicationOptions); - _traceChangeManager.TraceChanges(newTrack); - return Task.CompletedTask; - } - - void OnDeleteTrackClicked(Track track) - { - Cuesheet?.RemoveTrack(track); - selectedTracks.Remove(track); - } - - async Task EditSelectedTracksClicked() - { - if (modalTrackEdit != null) - { - modalTrackEdit.TracksToEdit = selectedTracks; - await modalTrackEdit.Show(); - } - } - - private void DeleteSelectedTracksClicked() - { - Cuesheet?.RemoveTracks(selectedTracks.AsReadOnly()); - selectedTracks.Clear(); - } - - async Task OnDeleteAllTracksClicked() - { - _logger.LogInformation("OnDeleteAllTracksClicked"); - //Display a confirm warning - if (modalDialog != null) - { - modalDialog.Title = _localizer["Confirmation required"]; - modalDialog.Text = _localizer["Do you really want to delete all tracks?"]; - modalDialog.ModalSize = ModalSize.Small; - modalDialog.Mode = ModalDialog.DialogMode.Confirm; - void deleteTracksDelegate(object? sender, EventArgs args) - { - _logger.LogInformation("deleteTracksDelegate"); - Cuesheet?.RemoveTracks(Cuesheet.Tracks); - selectedTracks.Clear(); - modalDialog.Confirmed -= deleteTracksDelegate; - StateHasChanged(); - }; - modalDialog.Confirmed += deleteTracksDelegate; - await modalDialog.ShowModal(); - } - } - - async Task EditTrackModal(Track trackToEdit) - { - if (modalTrackEdit != null) - { - modalTrackEdit.TracksToEdit = new List() { trackToEdit }; - await modalTrackEdit.Show(); - } - } - - private String? GetLocalizedString(Boolean expressionToCheck, String localizedStringName) - { - if (expressionToCheck == true) - { - return _localizer[localizedStringName]; - } - else - { - return null; - } - } - - bool SelectAllIndeterminate - { - get => selectedTracks.Count > 0 && selectedTracks.Count < Cuesheet?.Tracks.Count; - } - - private void SelectedTrackChanged(Track track, bool selected) - { - if (selected) - { - selectedTracks.Add(track); - } - else - { - selectedTracks.Remove(track); - } - } - - private void OnSelectAllTracks(bool select) - { - if (select) - { - if (Cuesheet != null) - { - foreach (var track in Cuesheet.Tracks) - { - if (!selectedTracks.Contains(track)) - { - selectedTracks.Add(track); - } - } - } - } - else - { - selectedTracks.Clear(); - } - } - - bool AllTracksSelected - { - get => selectedTracks.Count > 0 && selectedTracks.Count == Cuesheet?.Tracks.Count; - } - - async Task CopyTrackClicked(Track trackToCopy) - { - var copy = new Track(trackToCopy); - Cuesheet?.AddTrack(copy, applicationOptions); - _traceChangeManager.TraceChanges(copy); - await EditTrackModal(copy); - } - - private async Task OnPlayTrackClicked(Track track) - { - if (AudioPlayer != null) - { - await AudioPlayer.OnPlayTrackClicked(track); - } - } - - private void LocalizationService_LocalizationChanged(object? sender, EventArgs args) - { - StateHasChanged(); - validations?.ValidateAll(); - } - - private MarkupString GetMarkupString(String? stringValue) - { - MarkupString result = new MarkupString(String.Empty); - if (stringValue != null) - { - result = new MarkupString(stringValue); - } - return result; - } - - private void SessionStateContainer_CuesheetChanged(object? sender, EventArgs args) - { - DetachTrackFromValidateablePropertyChanged(); - DetachCuesheetFromSplitPointsAddedRemoved(); - selectedTracks.Clear(); - StateHasChanged(); - AttachTracksToValidateablePropertyChanged(); - AttachCuesheetToSplitPointsAddedRemoved(); - } - - private void SessionStateContainer_ImportCuesheetChanged(object? sender, EventArgs args) - { - // Unsubscribe to previous attached events - DetachCuesheetFromSplitPointsAddedRemoved(); - var tracks = TracksAttachedToValidateablePropertyChanged.Except(_sessionStateContainer.Cuesheet.Tracks); - for (int i = tracks.Count() - 1; i >= 0; i--) - { - var track = tracks.ElementAt(i); - DetachTrackFromValidateablePropertyChanged(track); - TracksAttachedToValidateablePropertyChanged.Remove(track); - } - // Reattach if needed - AttachTracksToValidateablePropertyChanged(); - AttachCuesheetToSplitPointsAddedRemoved(); - revalidate = true; - StateHasChanged(); - } - - private void TraceChangeManager_UndoDone(object? sender, EventArgs args) - { - StateHasChanged(); - } - - private void TraceChangeManager_RedoDone(object? sender, EventArgs args) - { - StateHasChanged(); - } - - void Cuesheet_TrackAdded(object? sender, TrackAddRemoveEventArgs args) - { - StateHasChanged(); - AttachTracksToValidateablePropertyChanged(); - revalidate = true; - } - - void Cuesheet_TrackRemoved(object? sender, TrackAddRemoveEventArgs args) - { - DetachTrackFromValidateablePropertyChanged(args.Track); - revalidate = true; - } - - async Task OnReadDataAutocompleteTrackArtist(AutocompleteReadDataEventArgs autocompleteReadDataEventArgs) - { - if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) - { - var artists = await _musicBrainzDataProvider.SearchArtistAsync(autocompleteReadDataEventArgs.SearchValue); - if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) - { - autocompleteTrackArtists = artists; - } - } - } - - async Task OnReadDataAutocompleteTrackTitle(AutocompleteReadDataEventArgs autocompleteReadDataEventArgs, Track track) - { - if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) - { - var titles = await _musicBrainzDataProvider.SearchTitleAsync(autocompleteReadDataEventArgs.SearchValue, track.Artist); - if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) - { - autocompleteTrackTitles = titles; - } - } - } - - async Task OnSelectedValueChangedTrackTitle(Guid selectedValue, Track track) - { - switch (_sessionStateContainer.CurrentViewMode) - { - case ViewMode.ViewModeFull: - case ViewMode.ViewModeImport: - var trackDetails = await _musicBrainzDataProvider.GetDetailsAsync(selectedValue); - if (trackDetails != null) - { - track.Length = trackDetails.Length; - if (String.IsNullOrEmpty(track.Artist)) - { - track.Artist = trackDetails.Artist; - } - } - break; - } - } - - void LocalStorageOptionsProvider_OptionSaved(object? sender, IOptions options) - { - if (options is ApplicationOptions) - { - applicationOptions = (ApplicationOptions)options; - } - } - - void AttachTracksToValidateablePropertyChanged() - { - if (Cuesheet != null) - { - foreach (var track in Cuesheet.Tracks) - { - if (TracksAttachedToValidateablePropertyChanged.Contains(track) == false) - { - track.ValidateablePropertyChanged += Track_ValidateablePropertyChanged; - TracksAttachedToValidateablePropertyChanged.Add(track); - } - } - } - } - - void DetachTrackFromValidateablePropertyChanged(Track? track = null) - { - if (track == null) - { - foreach (var trackCurrentlyAttached in TracksAttachedToValidateablePropertyChanged) - { - trackCurrentlyAttached.ValidateablePropertyChanged -= Track_ValidateablePropertyChanged; - } - } - else - { - track.ValidateablePropertyChanged -= Track_ValidateablePropertyChanged; - } - } - - void Track_ValidateablePropertyChanged(object? sender, string property) - { - if (validations != null) - { - validations.ValidateAll().GetAwaiter().GetResult(); - } - StateHasChanged(); - } - - void AttachCuesheetToSplitPointsAddedRemoved() - { - if (Cuesheet != null) - { - Cuesheet.SectionAdded += Cuesheet_SectionAdded; - Cuesheet.SectionRemoved += Cuesheet_SectionRemoved; - } - } - - void DetachCuesheetFromSplitPointsAddedRemoved() - { - if (Cuesheet != null) - { - Cuesheet.SectionAdded -= Cuesheet_SectionAdded; - Cuesheet.SectionRemoved -= Cuesheet_SectionRemoved; - } - } - - void Cuesheet_SectionAdded(object? sender, CuesheetSectionAddRemoveEventArgs args) - { - args.Section.ValidateablePropertyChanged += Section_ValidateablePropertyChanged; - } - - void Cuesheet_SectionRemoved(object? sender, CuesheetSectionAddRemoveEventArgs args) - { - args.Section.ValidateablePropertyChanged -= Section_ValidateablePropertyChanged; - } - - void Section_ValidateablePropertyChanged(object? sender, string property) - { - switch (property) - { - case nameof(CuesheetSection.Begin): - case nameof(CuesheetSection.End): - StateHasChanged(); - break; - } - } -} diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackList.razor b/AudioCuesheetEditor/Shared/TrackList/TrackList.razor new file mode 100644 index 00000000..1d027ad8 --- /dev/null +++ b/AudioCuesheetEditor/Shared/TrackList/TrackList.razor @@ -0,0 +1,489 @@ + + +@implements IDisposable + +@inject ITextLocalizer _localizer +@inject SessionStateContainer _sessionStateContainer +@inject ILocalStorageOptionsProvider _localStorageOptionsProvider +@inject TraceChangeManager _traceChangeManager +@inject ILogger _logger +@inject ITextLocalizerService _localizationService +@inject ITextLocalizer _validationMessageLocalizer + + + @if (_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull) + { + var validationResult = Cuesheet?.Validate(x => x.Tracks); + + + @_localizer["Validation errors"] + + @if (validationResult?.ValidationMessages != null) + { + @foreach(var message in validationResult.ValidationMessages) + { + @message.GetMessageLocalized(_validationMessageLocalizer) + } + } + + + + + + + + + + + @_localizer["Add new track"] + + + + + + @if (TrackSelectionVisible == false) + { + + + + + + + + @_localizer["Display selection of tracks"] + + + + } + else + { + + + + + + + + @_localizer["Hide selection of tracks"] + + + + } + + + + + + + + + + @_localizer["Edit selected tracks"] + + + + + + + + + + @_localizer["Delete selected tracks"] + + + + + + + + + + @_localizer["Delete all tracks"] + + + + + + + } + + + + + @if ((_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull) && (TrackSelectionVisible)) + { + + + @if (Cuesheet?.Tracks.Count > 0) + { + + + + } + @_localizer["Selection"] + + + } + @switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeFull: + case ViewMode.ViewModeImport: + @_localizer["Controls"] + break; + case ViewMode.ViewModeRecord: + @_localizer["Controls"] + break; + } + # + @_localizer["Artist"] + @_localizer["Title"] + @_localizer["Begin"] + @_localizer["End"] + @_localizer["Length"] + + + + + + + + + + + +@code { + ModalDialog? modalDialog; + EditTrackModal? modalTrackEdit; + List selectedTracks = new(); + Boolean _trackSelectionVisible = false; + Validations? validations; + Boolean revalidate = false; + List TracksAttachedToValidateablePropertyChanged = new(); + DropContainer? dropContainer; + + [Parameter] + public AudioPlayer? AudioPlayer { get; set; } + + public Cuesheet? Cuesheet + { + get + { + Cuesheet? cuesheet; + switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeImport: + cuesheet = _sessionStateContainer.ImportCuesheet; + break; + default: + cuesheet = _sessionStateContainer.Cuesheet; + break; + } + return cuesheet; + } + } + + public Boolean TrackSelectionVisible + { + get => _trackSelectionVisible; + set + { + _trackSelectionVisible = value; + selectedTracks = new(); + } + } + + public void Dispose() + { + _localizationService.LocalizationChanged -= LocalizationService_LocalizationChanged; + _sessionStateContainer.CuesheetChanged -= SessionStateContainer_CuesheetChanged; + _sessionStateContainer.ImportCuesheetChanged -= SessionStateContainer_ImportCuesheetChanged; + _traceChangeManager.UndoDone -= TraceChangeManager_UndoDone; + _traceChangeManager.RedoDone -= TraceChangeManager_RedoDone; + _sessionStateContainer.Cuesheet.TrackRemoved -= Cuesheet_TrackRemoved; + _sessionStateContainer.Cuesheet.TrackAdded -= Cuesheet_TrackAdded; + DetachTrackFromValidateablePropertyChanged(); + DetachCuesheetFromSplitPointsAddedRemoved(); + } + + protected override void OnInitialized() + { + base.OnInitialized(); + + _localizationService.LocalizationChanged += LocalizationService_LocalizationChanged; + + _sessionStateContainer.CuesheetChanged += SessionStateContainer_CuesheetChanged; + _sessionStateContainer.ImportCuesheetChanged += SessionStateContainer_ImportCuesheetChanged; + + _traceChangeManager.UndoDone += TraceChangeManager_UndoDone; + _traceChangeManager.RedoDone += TraceChangeManager_RedoDone; + + _sessionStateContainer.Cuesheet.TrackAdded += Cuesheet_TrackAdded; + _sessionStateContainer.Cuesheet.TrackRemoved += Cuesheet_TrackRemoved; + + AttachTracksToValidateablePropertyChanged(); + AttachCuesheetToSplitPointsAddedRemoved(); + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + _logger.LogDebug("OnAfterRenderAsync({firstRender})", firstRender); + if ((revalidate) && (validations != null)) + { + await validations.ValidateAll(); + revalidate = false; + } + } + + async Task OnAddTrackClicked() + { + var applicationOptions = await _localStorageOptionsProvider.GetOptions(); + var newTrack = new Track(); + Cuesheet?.AddTrack(newTrack, applicationOptions); + _traceChangeManager.TraceChanges(newTrack); + } + + async Task EditSelectedTracksClicked() + { + if (modalTrackEdit != null) + { + modalTrackEdit.TracksToEdit = selectedTracks; + await modalTrackEdit.Show(); + } + } + + private void DeleteSelectedTracksClicked() + { + Cuesheet?.RemoveTracks(selectedTracks.AsReadOnly()); + selectedTracks.Clear(); + } + + async Task OnDeleteAllTracksClicked() + { + _logger.LogInformation("OnDeleteAllTracksClicked"); + //Display a confirm warning + if (modalDialog != null) + { + modalDialog.Title = _localizer["Confirmation required"]; + modalDialog.Text = _localizer["Do you really want to delete all tracks?"]; + modalDialog.ModalSize = ModalSize.Small; + modalDialog.Mode = ModalDialog.DialogMode.Confirm; + void deleteTracksDelegate(object? sender, EventArgs args) + { + _logger.LogInformation("deleteTracksDelegate"); + Cuesheet?.RemoveTracks(Cuesheet.Tracks); + selectedTracks.Clear(); + modalDialog.Confirmed -= deleteTracksDelegate; + StateHasChanged(); + }; + modalDialog.Confirmed += deleteTracksDelegate; + await modalDialog.ShowModal(); + } + } + + private String? GetLocalizedString(Boolean expressionToCheck, String localizedStringName) + { + if (expressionToCheck == true) + { + return _localizer[localizedStringName]; + } + else + { + return null; + } + } + + bool SelectAllIndeterminate + { + get => selectedTracks.Count > 0 && selectedTracks.Count < Cuesheet?.Tracks.Count; + } + + private void OnSelectAllTracks(bool select) + { + if (select) + { + if (Cuesheet != null) + { + foreach (var track in Cuesheet.Tracks) + { + if (!selectedTracks.Contains(track)) + { + selectedTracks.Add(track); + } + } + } + } + else + { + selectedTracks.Clear(); + } + } + + bool AllTracksSelected + { + get => selectedTracks.Count > 0 && selectedTracks.Count == Cuesheet?.Tracks.Count; + } + + private void LocalizationService_LocalizationChanged(object? sender, EventArgs args) + { + StateHasChanged(); + validations?.ValidateAll(); + } + + private MarkupString GetMarkupString(String? stringValue) + { + MarkupString result = new MarkupString(String.Empty); + if (stringValue != null) + { + result = new MarkupString(stringValue); + } + return result; + } + + private void SessionStateContainer_CuesheetChanged(object? sender, EventArgs args) + { + DetachTrackFromValidateablePropertyChanged(); + DetachCuesheetFromSplitPointsAddedRemoved(); + selectedTracks.Clear(); + StateHasChanged(); + AttachTracksToValidateablePropertyChanged(); + AttachCuesheetToSplitPointsAddedRemoved(); + } + + private void SessionStateContainer_ImportCuesheetChanged(object? sender, EventArgs args) + { + // Unsubscribe to previous attached events + DetachCuesheetFromSplitPointsAddedRemoved(); + var tracks = TracksAttachedToValidateablePropertyChanged.Except(_sessionStateContainer.Cuesheet.Tracks); + for (int i = tracks.Count() - 1; i >= 0; i--) + { + var track = tracks.ElementAt(i); + DetachTrackFromValidateablePropertyChanged(track); + TracksAttachedToValidateablePropertyChanged.Remove(track); + } + // Reattach if needed + AttachTracksToValidateablePropertyChanged(); + AttachCuesheetToSplitPointsAddedRemoved(); + revalidate = true; + StateHasChanged(); + } + + private void TraceChangeManager_UndoDone(object? sender, EventArgs args) + { + StateHasChanged(); + } + + private void TraceChangeManager_RedoDone(object? sender, EventArgs args) + { + StateHasChanged(); + } + + void Cuesheet_TrackAdded(object? sender, TrackAddRemoveEventArgs args) + { + StateHasChanged(); + dropContainer?.Refresh(); + AttachTracksToValidateablePropertyChanged(); + revalidate = true; + } + + void Cuesheet_TrackRemoved(object? sender, TrackAddRemoveEventArgs args) + { + dropContainer?.Refresh(); + DetachTrackFromValidateablePropertyChanged(args.Track); + revalidate = true; + } + + void AttachTracksToValidateablePropertyChanged() + { + if (Cuesheet != null) + { + foreach (var track in Cuesheet.Tracks) + { + if (TracksAttachedToValidateablePropertyChanged.Contains(track) == false) + { + track.ValidateablePropertyChanged += Track_ValidateablePropertyChanged; + TracksAttachedToValidateablePropertyChanged.Add(track); + } + } + } + } + + void DetachTrackFromValidateablePropertyChanged(Track? track = null) + { + if (track == null) + { + foreach (var trackCurrentlyAttached in TracksAttachedToValidateablePropertyChanged) + { + trackCurrentlyAttached.ValidateablePropertyChanged -= Track_ValidateablePropertyChanged; + } + } + else + { + track.ValidateablePropertyChanged -= Track_ValidateablePropertyChanged; + } + } + + void Track_ValidateablePropertyChanged(object? sender, string property) + { + if (validations != null) + { + validations.ValidateAll().GetAwaiter().GetResult(); + } + StateHasChanged(); + } + + void AttachCuesheetToSplitPointsAddedRemoved() + { + if (Cuesheet != null) + { + Cuesheet.SectionAdded += Cuesheet_SectionAdded; + Cuesheet.SectionRemoved += Cuesheet_SectionRemoved; + } + } + + void DetachCuesheetFromSplitPointsAddedRemoved() + { + if (Cuesheet != null) + { + Cuesheet.SectionAdded -= Cuesheet_SectionAdded; + Cuesheet.SectionRemoved -= Cuesheet_SectionRemoved; + } + } + + void Cuesheet_SectionAdded(object? sender, CuesheetSectionAddRemoveEventArgs args) + { + args.Section.ValidateablePropertyChanged += Section_ValidateablePropertyChanged; + } + + void Cuesheet_SectionRemoved(object? sender, CuesheetSectionAddRemoveEventArgs args) + { + args.Section.ValidateablePropertyChanged -= Section_ValidateablePropertyChanged; + } + + void Section_ValidateablePropertyChanged(object? sender, string property) + { + switch (property) + { + case nameof(CuesheetSection.Begin): + case nameof(CuesheetSection.End): + StateHasChanged(); + break; + } + } +} diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor b/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor new file mode 100644 index 00000000..24b19a35 --- /dev/null +++ b/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor @@ -0,0 +1,399 @@ + +@implements IDisposable + +@inject ITextLocalizer _localizer +@inject SessionStateContainer _sessionStateContainer +@inject ITextLocalizer _validationMessageLocalizer +@inject TraceChangeManager _traceChangeManager +@inject ApplicationOptionsTimeSpanParser _applicationOptionsTimeSpanParser +@inject MusicBrainzDataProvider _musicBrainzDataProvider +@inject ITextLocalizerService _localizationService + + + @if (Cuesheet != null) + { + + @if ((track != Cuesheet?.Tracks.FirstOrDefault()) && (_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull)) + { + + + @if (track.IsLinkedToPreviousTrack) + { + + + + + @_localizer["Unlink this track from previous track"] + + } + else + { + + + + + @_localizer["Link this track with previous track"] + + } + + + } + + + @switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeRecord: + + + + + + + + @track.Position + break; + case ViewMode.ViewModeFull: + case ViewMode.ViewModeImport: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + break; + } + + + + + @if (context.Item.Disambiguation != null) + { + @String.Format("{0} ({1})", context.Text, context.Item.Disambiguation) + } + else + { + @context.Text + } + + + + + + + + + @if (context.Item.Disambiguation != null) + { + @String.Format("{0} ({1})", context.Text, context.Item.Disambiguation) + } + else + { + @context.Text + } + + + + + @switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeRecord: + @track.Begin + @track.End + @track.Length + break; + case ViewMode.ViewModeFull: + case ViewMode.ViewModeImport: + + + @if (Cuesheet?.GetSectionAtTrack(track) != null) + { + + + + + + + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + break; + } + + + } + + + + +@code { + //TODO: More little components, like TrackLink, TrackSelection, etc. ;) + //TODO: Localization + Validations? validations; + EditTrackModal? modalTrackEdit; + IEnumerable? autocompleteTrackArtists; + IEnumerable? autocompleteTrackTitles; + + public void Dispose() + { + _localizationService.LocalizationChanged -= LocalizationService_LocalizationChanged; + } + + [Parameter, EditorRequired] + public Boolean TrackSelectionVisible { get; set; } + + [Parameter, EditorRequired] + public IReadOnlyCollection SelectedTracks { get; set; } = new List(); + + [Parameter] + public EventCallback> SelectedTracksChanged { get; set; } + + [Parameter] + public AudioPlayer? AudioPlayer { get; set; } + + public Cuesheet? Cuesheet + { + get + { + Cuesheet? cuesheet; + switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeImport: + cuesheet = _sessionStateContainer.ImportCuesheet; + break; + default: + cuesheet = _sessionStateContainer.Cuesheet; + break; + } + return cuesheet; + } + } + + protected override void OnInitialized() + { + base.OnInitialized(); + _localizationService.LocalizationChanged += LocalizationService_LocalizationChanged; + } + + void LocalizationService_LocalizationChanged(object? sender, EventArgs args) + { + StateHasChanged(); + validations?.ValidateAll(); + } + + String? GetLocalizedString(Boolean expressionToCheck, String localizedStringName) + { + if (expressionToCheck == true) + { + return _localizer[localizedStringName]; + } + else + { + return null; + } + } + + async Task EditTrackModal(Track trackToEdit) + { + if (modalTrackEdit != null) + { + modalTrackEdit.TracksToEdit = new List() { trackToEdit }; + await modalTrackEdit.Show(); + } + } + + async Task CopyTrackClicked(Track trackToCopy) + { + var copy = new Track(trackToCopy); + //TODO + // Cuesheet?.AddTrack(copy, applicationOptions); + _traceChangeManager.TraceChanges(copy); + await EditTrackModal(copy); + } + + async Task OnPlayTrackClicked(Track track) + { + if (AudioPlayer != null) + { + await AudioPlayer.OnPlayTrackClicked(track); + } + } + + void SelectedTrackChanged(Track track, bool selected) + { + var selectedTracks = new List(SelectedTracks); + if (selected) + { + selectedTracks.Add(track); + } + else + { + selectedTracks.Remove(track); + } + SelectedTracksChanged.InvokeAsync(selectedTracks); + } + + void OnDeleteTrackClicked(Track track) + { + Cuesheet?.RemoveTrack(track); + var selectedTracks = new List(SelectedTracks); + selectedTracks.Remove(track); + SelectedTracksChanged.InvokeAsync(selectedTracks); + } + + async Task OnReadDataAutocompleteTrackArtist(AutocompleteReadDataEventArgs autocompleteReadDataEventArgs) + { + if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) + { + var artists = await _musicBrainzDataProvider.SearchArtistAsync(autocompleteReadDataEventArgs.SearchValue); + if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) + { + autocompleteTrackArtists = artists; + } + } + } + + async Task OnReadDataAutocompleteTrackTitle(AutocompleteReadDataEventArgs autocompleteReadDataEventArgs, Track track) + { + if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) + { + var titles = await _musicBrainzDataProvider.SearchTitleAsync(autocompleteReadDataEventArgs.SearchValue, track.Artist); + if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) + { + autocompleteTrackTitles = titles; + } + } + } + + async Task OnSelectedValueChangedTrackTitle(Guid selectedValue, Track track) + { + switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeFull: + case ViewMode.ViewModeImport: + var trackDetails = await _musicBrainzDataProvider.GetDetailsAsync(selectedValue); + if (trackDetails != null) + { + track.Length = trackDetails.Length; + if (String.IsNullOrEmpty(track.Artist)) + { + track.Artist = trackDetails.Artist; + } + } + break; + } + } +} diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackSelection.razor b/AudioCuesheetEditor/Shared/TrackList/TrackSelection.razor new file mode 100644 index 00000000..329be82a --- /dev/null +++ b/AudioCuesheetEditor/Shared/TrackList/TrackSelection.razor @@ -0,0 +1,59 @@ + +@implements IDisposable + +@inject ITextLocalizer _localizer +@inject ITextLocalizerService _localizationService + +@if (Visible) +{ + + + + + +} + +@code { + //TODO: Localization + + [Parameter, EditorRequired] + public Boolean Visible { get; set; } + + [Parameter, EditorRequired] + public bool Selected { get; set; } + + [Parameter, EditorRequired] + public EventCallback SelectedChanged { get; set; } + + public void Dispose() + { + _localizationService.LocalizationChanged -= LocalizationService_LocalizationChanged; + } + + protected override void OnInitialized() + { + base.OnInitialized(); + _localizationService.LocalizationChanged += LocalizationService_LocalizationChanged; + } + + void LocalizationService_LocalizationChanged(object? sender, EventArgs args) + { + StateHasChanged(); + } +} diff --git a/AudioCuesheetEditor/_Imports.razor b/AudioCuesheetEditor/_Imports.razor index b86c652b..61538055 100644 --- a/AudioCuesheetEditor/_Imports.razor +++ b/AudioCuesheetEditor/_Imports.razor @@ -12,6 +12,7 @@ @using AudioCuesheetEditor @using AudioCuesheetEditor.Pages @using AudioCuesheetEditor.Shared +@using AudioCuesheetEditor.Shared.TrackList @using AudioCuesheetEditor.Model.AudioCuesheet @using AudioCuesheetEditor.Model.IO @using AudioCuesheetEditor.Model.IO.Export From c1e0f0f485cfb5077d15f5b00a6b9a75c015ba97 Mon Sep 17 00:00:00 2001 From: NeoCoderMatrix86 <40752681+NeoCoderMatrix86@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:46:09 +0100 Subject: [PATCH 04/30] Update TrackList.razor --- AudioCuesheetEditor/Shared/TrackList/TrackList.razor | 3 --- 1 file changed, 3 deletions(-) diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackList.razor b/AudioCuesheetEditor/Shared/TrackList/TrackList.razor index 1d027ad8..cf125467 100644 --- a/AudioCuesheetEditor/Shared/TrackList/TrackList.razor +++ b/AudioCuesheetEditor/Shared/TrackList/TrackList.razor @@ -175,7 +175,6 @@ along with Foobar. If not, see Validations? validations; Boolean revalidate = false; List TracksAttachedToValidateablePropertyChanged = new(); - DropContainer? dropContainer; [Parameter] public AudioPlayer? AudioPlayer { get; set; } @@ -397,14 +396,12 @@ along with Foobar. If not, see void Cuesheet_TrackAdded(object? sender, TrackAddRemoveEventArgs args) { StateHasChanged(); - dropContainer?.Refresh(); AttachTracksToValidateablePropertyChanged(); revalidate = true; } void Cuesheet_TrackRemoved(object? sender, TrackAddRemoveEventArgs args) { - dropContainer?.Refresh(); DetachTrackFromValidateablePropertyChanged(args.Track); revalidate = true; } From b81048574398e6abcf7f7c0a1bd1f0a2be716c23 Mon Sep 17 00:00:00 2001 From: NeoCoderMatrix86 <40752681+NeoCoderMatrix86@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:18:47 +0100 Subject: [PATCH 05/30] Add tracklink component --- .../AudioCuesheetEditor.csproj | 6 +- .../Localization/TrackLinkControl/de.json | 7 ++ .../Localization/TrackLinkControl/en.json | 7 ++ .../Resources/Localization/TrackList/de.json | 2 - .../Resources/Localization/TrackList/en.json | 2 - .../Shared/TrackList/TrackLinkControl.razor | 98 +++++++++++++++++++ .../Shared/TrackList/TrackListItem.razor | 26 +---- 7 files changed, 117 insertions(+), 31 deletions(-) create mode 100644 AudioCuesheetEditor/Resources/Localization/TrackLinkControl/de.json create mode 100644 AudioCuesheetEditor/Resources/Localization/TrackLinkControl/en.json create mode 100644 AudioCuesheetEditor/Shared/TrackList/TrackLinkControl.razor diff --git a/AudioCuesheetEditor/AudioCuesheetEditor.csproj b/AudioCuesheetEditor/AudioCuesheetEditor.csproj index 520f5836..78e416b8 100644 --- a/AudioCuesheetEditor/AudioCuesheetEditor.csproj +++ b/AudioCuesheetEditor/AudioCuesheetEditor.csproj @@ -41,8 +41,6 @@ - - @@ -51,6 +49,8 @@ + + @@ -88,6 +88,8 @@ + + diff --git a/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/de.json b/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/de.json new file mode 100644 index 00000000..5c21be15 --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/de.json @@ -0,0 +1,7 @@ +{ + "culture": "de", + "translations": { + "Unlink this track from previous track": "Diesen Titel vom vorherigen Titel abkoppeln", + "Link this track with previous track": "Diesen Titel an den vorherigen Titel koppeln" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/en.json b/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/en.json new file mode 100644 index 00000000..5effbf15 --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/en.json @@ -0,0 +1,7 @@ +{ + "culture": "en", + "translations": { + "Unlink this track from previous track": "Unlink this track from previous track", + "Link this track with previous track": "Link this track with previous track" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TrackList/de.json b/AudioCuesheetEditor/Resources/Localization/TrackList/de.json index 3a738f1a..6afcf109 100644 --- a/AudioCuesheetEditor/Resources/Localization/TrackList/de.json +++ b/AudioCuesheetEditor/Resources/Localization/TrackList/de.json @@ -15,8 +15,6 @@ "Begin": "Beginn", "End": "Ende", "Length": "Länge", - "Unlink this track from previous track": "Diesen Titel vom vorherigen Titel abkoppeln", - "Link this track with previous track": "Diesen Titel an den vorherigen Titel koppeln", "Current track is played": "Dieser Track wird aktuell wiedergegeben", "Edit track tooltip": "Titeldetails in einem Dialog bearbeiten", "Copy track tooltip": "Kopiere diesen Titel mit allen Werten und füge ihn anschließend zum Cuesheet hinzu.", diff --git a/AudioCuesheetEditor/Resources/Localization/TrackList/en.json b/AudioCuesheetEditor/Resources/Localization/TrackList/en.json index 819ccbf3..0ffcee82 100644 --- a/AudioCuesheetEditor/Resources/Localization/TrackList/en.json +++ b/AudioCuesheetEditor/Resources/Localization/TrackList/en.json @@ -15,8 +15,6 @@ "Begin": "Begin", "End": "End", "Length": "Length", - "Unlink this track from previous track": "Unlink this track from previous track", - "Link this track with previous track": "Link this track with previous track", "Current track is played": "Current track is played", "Edit track tooltip": "Edit track details in a dialog", "Copy track tooltip": "Copy this track with all values and attach it to the cuesheet.", diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackLinkControl.razor b/AudioCuesheetEditor/Shared/TrackList/TrackLinkControl.razor new file mode 100644 index 00000000..40260a05 --- /dev/null +++ b/AudioCuesheetEditor/Shared/TrackList/TrackLinkControl.razor @@ -0,0 +1,98 @@ + +@implements IDisposable + +@inject ITextLocalizer _localizer +@inject ITextLocalizerService _localizationService +@inject SessionStateContainer _sessionStateContainer + +@if ((TrackReference != Cuesheet?.Tracks.FirstOrDefault()) && (_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull)) +{ + + + @if (TrackReference?.IsLinkedToPreviousTrack == true) + { + + + + + @_localizer["Unlink this track from previous track"] + + } + else + { + + + + + @_localizer["Link this track with previous track"] + + } + + +} + +@code { + [Parameter, EditorRequired] + public Boolean TrackSelectionVisible { get; set; } + + [Parameter, EditorRequired] + public Track? TrackReference { get; set; } + + public Cuesheet? Cuesheet + { + get + { + Cuesheet? cuesheet; + switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeImport: + cuesheet = _sessionStateContainer.ImportCuesheet; + break; + default: + cuesheet = _sessionStateContainer.Cuesheet; + break; + } + return cuesheet; + } + } + + public void Dispose() + { + _localizationService.LocalizationChanged -= LocalizationService_LocalizationChanged; + } + + protected override void OnInitialized() + { + base.OnInitialized(); + _localizationService.LocalizationChanged += LocalizationService_LocalizationChanged; + } + + void LocalizationService_LocalizationChanged(object? sender, EventArgs args) + { + StateHasChanged(); + } + + void SetLink(Boolean linkState) + { + if (TrackReference != null) + { + TrackReference.IsLinkedToPreviousTrack = linkState; + } + } +} diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor b/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor index 24b19a35..6c789e81 100644 --- a/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor +++ b/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor @@ -29,31 +29,7 @@ along with Foobar. If not, see @if (Cuesheet != null) { - @if ((track != Cuesheet?.Tracks.FirstOrDefault()) && (_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull)) - { - - - @if (track.IsLinkedToPreviousTrack) - { - - - - - @_localizer["Unlink this track from previous track"] - - } - else - { - - - - - @_localizer["Link this track with previous track"] - - } - - - } + @switch (_sessionStateContainer.CurrentViewMode) From f82d25f5c225d27964992c51361a920be622452f Mon Sep 17 00:00:00 2001 From: NeoCoderMatrix86 <40752681+NeoCoderMatrix86@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:21:55 +0100 Subject: [PATCH 06/30] Update TrackListItem.razor --- AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor b/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor index 6c789e81..f9bf3450 100644 --- a/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor +++ b/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor @@ -24,6 +24,7 @@ along with Foobar. If not, see @inject ApplicationOptionsTimeSpanParser _applicationOptionsTimeSpanParser @inject MusicBrainzDataProvider _musicBrainzDataProvider @inject ITextLocalizerService _localizationService +@inject ILocalStorageOptionsProvider _localStorageOptionsProvider @if (Cuesheet != null) @@ -294,8 +295,8 @@ along with Foobar. If not, see async Task CopyTrackClicked(Track trackToCopy) { var copy = new Track(trackToCopy); - //TODO - // Cuesheet?.AddTrack(copy, applicationOptions); + var applicationOptions = await _localStorageOptionsProvider.GetOptions(); + Cuesheet?.AddTrack(copy, applicationOptions); _traceChangeManager.TraceChanges(copy); await EditTrackModal(copy); } From 4b8bd989aa6a4dcdec1df423be1ef792b468bc61 Mon Sep 17 00:00:00 2001 From: NeoCoderMatrix86 <40752681+NeoCoderMatrix86@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:30:24 +0100 Subject: [PATCH 07/30] New component for tracklist control column --- .../Shared/TrackList/TrackListItem.razor | 117 +--------- .../TrackListItemControlColumn.razor | 212 ++++++++++++++++++ 2 files changed, 222 insertions(+), 107 deletions(-) create mode 100644 AudioCuesheetEditor/Shared/TrackList/TrackListItemControlColumn.razor diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor b/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor index f9bf3450..cfb6e292 100644 --- a/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor +++ b/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor @@ -33,94 +33,7 @@ along with Foobar. If not, see - @switch (_sessionStateContainer.CurrentViewMode) - { - case ViewMode.ViewModeRecord: - - - - - - - - @track.Position - break; - case ViewMode.ViewModeFull: - case ViewMode.ViewModeImport: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - break; - } + @@ -217,10 +130,9 @@ along with Foobar. If not, see @code { - //TODO: More little components, like TrackLink, TrackSelection, etc. ;) //TODO: Localization - Validations? validations; EditTrackModal? modalTrackEdit; + Validations? validations; IEnumerable? autocompleteTrackArtists; IEnumerable? autocompleteTrackTitles; @@ -238,7 +150,7 @@ along with Foobar. If not, see [Parameter] public EventCallback> SelectedTracksChanged { get; set; } - [Parameter] + [Parameter, EditorRequired] public AudioPlayer? AudioPlayer { get; set; } public Cuesheet? Cuesheet @@ -301,14 +213,6 @@ along with Foobar. If not, see await EditTrackModal(copy); } - async Task OnPlayTrackClicked(Track track) - { - if (AudioPlayer != null) - { - await AudioPlayer.OnPlayTrackClicked(track); - } - } - void SelectedTrackChanged(Track track, bool selected) { var selectedTracks = new List(SelectedTracks); @@ -323,14 +227,6 @@ along with Foobar. If not, see SelectedTracksChanged.InvokeAsync(selectedTracks); } - void OnDeleteTrackClicked(Track track) - { - Cuesheet?.RemoveTrack(track); - var selectedTracks = new List(SelectedTracks); - selectedTracks.Remove(track); - SelectedTracksChanged.InvokeAsync(selectedTracks); - } - async Task OnReadDataAutocompleteTrackArtist(AutocompleteReadDataEventArgs autocompleteReadDataEventArgs) { if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) @@ -373,4 +269,11 @@ along with Foobar. If not, see break; } } + + void TrackDeleted(Track track) + { + var selectedTracks = new List(SelectedTracks); + selectedTracks.Remove(track); + SelectedTracksChanged.InvokeAsync(selectedTracks); + } } diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackListItemControlColumn.razor b/AudioCuesheetEditor/Shared/TrackList/TrackListItemControlColumn.razor new file mode 100644 index 00000000..84a75095 --- /dev/null +++ b/AudioCuesheetEditor/Shared/TrackList/TrackListItemControlColumn.razor @@ -0,0 +1,212 @@ +