From b23c46f79f517ac484b86b8879b6b56af895750d Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Tue, 6 May 2025 15:32:59 -0600 Subject: [PATCH 1/9] Fix incorrect chapters in some audiobooks (#1210) --- Source/FileLiberator/DownloadOptions.Factory.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/FileLiberator/DownloadOptions.Factory.cs b/Source/FileLiberator/DownloadOptions.Factory.cs index 6e9d71ac..7c3d3c81 100644 --- a/Source/FileLiberator/DownloadOptions.Factory.cs +++ b/Source/FileLiberator/DownloadOptions.Factory.cs @@ -27,6 +27,15 @@ public partial class DownloadOptions public static async Task InitiateDownloadAsync(Api api, Configuration config, LibraryBook libraryBook) { var license = await ChooseContent(api, libraryBook, config); + + //Come audiobooks will have incorrect chapters in the metadata returned from the license request, + //but the metadata returned by the content metadata endpoint will be correct. Call the content + //metadata endpoint and use its chapters. Only replace the license request chapters if the total + //lengths match (defensive against different audio formats having slightly different lengths). + var metadata = await api.GetContentMetadataAsync(libraryBook.Book.AudibleProductId); + if (metadata.ChapterInfo.RuntimeLengthMs == license.ContentMetadata.ChapterInfo.RuntimeLengthMs) + license.ContentMetadata.ChapterInfo = metadata.ChapterInfo; + var options = BuildDownloadOptions(libraryBook, config, license); return options; @@ -356,7 +365,7 @@ public partial class DownloadOptions else if (titleConcat is null) { chaps.Add(c); - chaps.AddRange(flattenChapters(c.Chapters)); + chaps.AddRange(flattenChapters(c.Chapters, titleConcat)); } else { @@ -369,7 +378,7 @@ public partial class DownloadOptions else chaps.Add(c); - var children = flattenChapters(c.Chapters); + var children = flattenChapters(c.Chapters, titleConcat); foreach (var child in children) child.Title = $"{c.Title}{titleConcat}{child.Title}"; From 5ab6c1fe70701a3fcd66f9c872b7e9e38d0db10e Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Tue, 6 May 2025 15:33:38 -0600 Subject: [PATCH 2/9] Update AAXClean to fix metadata reader (#1243 ) --- Source/AaxDecrypter/AaxDecrypter.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/AaxDecrypter/AaxDecrypter.csproj b/Source/AaxDecrypter/AaxDecrypter.csproj index 4a034939..8255f5b9 100644 --- a/Source/AaxDecrypter/AaxDecrypter.csproj +++ b/Source/AaxDecrypter/AaxDecrypter.csproj @@ -13,7 +13,7 @@ - + From 8aa157f2f6338cd631774bd6db3701a49ed90789 Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Tue, 6 May 2025 15:43:58 -0600 Subject: [PATCH 3/9] Re-add completed audiobooks to queue (#1219) --- Source/LibationAvalonia/ViewModels/MainVM.ProcessQueue.cs | 6 ++++++ Source/LibationAvalonia/ViewModels/ProcessQueueViewModel.cs | 5 +++++ Source/LibationWinForms/Form1.ProcessQueue.cs | 6 ++++++ Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs | 5 +++++ 4 files changed, 22 insertions(+) diff --git a/Source/LibationAvalonia/ViewModels/MainVM.ProcessQueue.cs b/Source/LibationAvalonia/ViewModels/MainVM.ProcessQueue.cs index 69dc697c..b964e6b9 100644 --- a/Source/LibationAvalonia/ViewModels/MainVM.ProcessQueue.cs +++ b/Source/LibationAvalonia/ViewModels/MainVM.ProcessQueue.cs @@ -40,6 +40,12 @@ namespace LibationAvalonia.ViewModels if (libraryBooks.Length == 1) { var item = libraryBooks[0]; + + //Remove this item from the queue if it's already present and completed. + //Only do this when adding a single book at a time to prevent accidental + //extra downloads when queueing in batches. + ProcessQueue.RemoveCompleted(item); + if (item.Book.UserDefinedItem.BookStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload) { Serilog.Log.Logger.Information("Begin single book backup of {libraryBook}", item); diff --git a/Source/LibationAvalonia/ViewModels/ProcessQueueViewModel.cs b/Source/LibationAvalonia/ViewModels/ProcessQueueViewModel.cs index e318977c..29620384 100644 --- a/Source/LibationAvalonia/ViewModels/ProcessQueueViewModel.cs +++ b/Source/LibationAvalonia/ViewModels/ProcessQueueViewModel.cs @@ -130,6 +130,11 @@ namespace LibationAvalonia.ViewModels return true; } + public bool RemoveCompleted(LibraryBook libraryBook) + => Queue.FirstOrDefault(b => b?.LibraryBook?.Book?.AudibleProductId == libraryBook.Book.AudibleProductId) is ProcessBookViewModel entry + && entry.Status is ProcessBookStatus.Completed + && Queue.RemoveCompleted(entry); + public void AddDownloadPdf(LibraryBook libraryBook) => AddDownloadPdf(new List() { libraryBook }); diff --git a/Source/LibationWinForms/Form1.ProcessQueue.cs b/Source/LibationWinForms/Form1.ProcessQueue.cs index 5c2e86c9..f9c7ccc4 100644 --- a/Source/LibationWinForms/Form1.ProcessQueue.cs +++ b/Source/LibationWinForms/Form1.ProcessQueue.cs @@ -30,6 +30,12 @@ namespace LibationWinForms if (libraryBooks.Length == 1) { var item = libraryBooks[0]; + + //Remove this item from the queue if it's already present and completed. + //Only do this when adding a single book at a time to prevent accidental + //extra downloads when queueing in batches. + processBookQueue1.RemoveCompleted(item); + if (item.Book.UserDefinedItem.BookStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload) { Serilog.Log.Logger.Information("Begin single book backup of {libraryBook}", item); diff --git a/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs b/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs index c993c8b6..5f10bc04 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs @@ -92,6 +92,11 @@ namespace LibationWinForms.ProcessQueue return true; } + public bool RemoveCompleted(DataLayer.LibraryBook libraryBook) + => Queue.FirstOrDefault(b => b?.LibraryBook?.Book?.AudibleProductId == libraryBook.Book.AudibleProductId) is ProcessBook entry + && entry.Status is ProcessBookStatus.Completed + && Queue.RemoveCompleted(entry); + public void AddDownloadPdf(DataLayer.LibraryBook libraryBook) => AddDownloadPdf(new List() { libraryBook }); From 52d3b9cb67726914e9ad94c8ab2d7f974b1df2d4 Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Wed, 7 May 2025 10:36:43 -0600 Subject: [PATCH 4/9] Disable warning --- Source/DataLayer/EfClasses/Book.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/DataLayer/EfClasses/Book.cs b/Source/DataLayer/EfClasses/Book.cs index 05ccd9e6..33cbbaf5 100644 --- a/Source/DataLayer/EfClasses/Book.cs +++ b/Source/DataLayer/EfClasses/Book.cs @@ -43,9 +43,11 @@ namespace DataLayer public ContentType ContentType { get; private set; } public string Locale { get; private set; } - //This field is now unused, however, there is little sense in adding a - //database migration to remove an unused field. Leave it for compatibility. - internal long _audioFormat; + //This field is now unused, however, there is little sense in adding a + //database migration to remove an unused field. Leave it for compatibility. +#pragma warning disable CS0649 // Field 'Book._audioFormat' is never assigned to, and will always have its default value 0 + internal long _audioFormat; +#pragma warning restore CS0649 // mutable public string PictureId { get; set; } From 45472abd1f6a8759643d29e3c0ad66b817978b82 Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Wed, 7 May 2025 11:15:32 -0600 Subject: [PATCH 5/9] Update dependencies --- Source/HangoverAvalonia/HangoverAvalonia.csproj | 10 +++++----- Source/LibationAvalonia/LibationAvalonia.csproj | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/HangoverAvalonia/HangoverAvalonia.csproj b/Source/HangoverAvalonia/HangoverAvalonia.csproj index b90c1b09..2f0ea40d 100644 --- a/Source/HangoverAvalonia/HangoverAvalonia.csproj +++ b/Source/HangoverAvalonia/HangoverAvalonia.csproj @@ -71,13 +71,13 @@ - - + + - - + + - + diff --git a/Source/LibationAvalonia/LibationAvalonia.csproj b/Source/LibationAvalonia/LibationAvalonia.csproj index 0c024628..04741857 100644 --- a/Source/LibationAvalonia/LibationAvalonia.csproj +++ b/Source/LibationAvalonia/LibationAvalonia.csproj @@ -73,14 +73,14 @@ - - - - + + + + - - - + + + From 0df17a2296dfbfeb3afb800a75efb15322b53307 Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Wed, 7 May 2025 13:12:12 -0600 Subject: [PATCH 6/9] Remove retired ItemsRepeater control --- .../Controls/CheckedListBox.axaml | 25 ++--- .../Controls/CheckedListBox.axaml.cs | 105 ++---------------- .../HangoverAvalonia/HangoverAvalonia.csproj | 1 - .../ViewModels/CheckBoxViewModel.cs | 11 ++ .../Controls/CheckedListBox.axaml | 25 ++--- .../Controls/CheckedListBox.axaml.cs | 14 --- .../LibationAvalonia/LibationAvalonia.csproj | 1 - .../Views/ProcessQueueControl.axaml | 33 ++---- 8 files changed, 46 insertions(+), 169 deletions(-) create mode 100644 Source/HangoverAvalonia/ViewModels/CheckBoxViewModel.cs diff --git a/Source/HangoverAvalonia/Controls/CheckedListBox.axaml b/Source/HangoverAvalonia/Controls/CheckedListBox.axaml index b7d8c94d..a1750735 100644 --- a/Source/HangoverAvalonia/Controls/CheckedListBox.axaml +++ b/Source/HangoverAvalonia/Controls/CheckedListBox.axaml @@ -4,27 +4,16 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="HangoverAvalonia.Controls.CheckedListBox"> - - - - - - - - - - - - - + + + + + + + diff --git a/Source/HangoverAvalonia/Controls/CheckedListBox.axaml.cs b/Source/HangoverAvalonia/Controls/CheckedListBox.axaml.cs index bdcfcf61..26ea99b8 100644 --- a/Source/HangoverAvalonia/Controls/CheckedListBox.axaml.cs +++ b/Source/HangoverAvalonia/Controls/CheckedListBox.axaml.cs @@ -2,103 +2,18 @@ using Avalonia; using Avalonia.Collections; using Avalonia.Controls; using HangoverAvalonia.ViewModels; -using ReactiveUI; -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -namespace HangoverAvalonia.Controls +namespace HangoverAvalonia.Controls; + +public partial class CheckedListBox : UserControl { - public partial class CheckedListBox : UserControl + public static readonly StyledProperty> ItemsProperty = + AvaloniaProperty.Register>(nameof(Items)); + + public AvaloniaList Items { get => GetValue(ItemsProperty); set => SetValue(ItemsProperty, value); } + + public CheckedListBox() { - public event EventHandler ItemCheck; - - public static readonly StyledProperty ItemsProperty = - AvaloniaProperty.Register(nameof(Items)); - - public IEnumerable Items { get => GetValue(ItemsProperty); set => SetValue(ItemsProperty, value); } - private CheckedListBoxViewModel _viewModel = new(); - - public IEnumerable CheckedItems => - _viewModel - .CheckboxItems - .Where(i => i.IsChecked) - .Select(i => i.Item); - - public void SetItemChecked(int i, bool isChecked) => _viewModel.CheckboxItems[i].IsChecked = isChecked; - public void SetItemChecked(object item, bool isChecked) - { - var obj = _viewModel.CheckboxItems.SingleOrDefault(i => i.Item == item); - if (obj is not null) - obj.IsChecked = isChecked; - } - - public CheckedListBox() - { - InitializeComponent(); - scroller.DataContext = _viewModel; - _viewModel.CheckedChanged += _viewModel_CheckedChanged; - } - - private void _viewModel_CheckedChanged(object sender, CheckBoxViewModel e) - { - var args = new ItemCheckEventArgs { Item = e.Item, ItemIndex = _viewModel.CheckboxItems.IndexOf(e), IsChecked = e.IsChecked }; - ItemCheck?.Invoke(this, args); - } - - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) - { - if (change.Property.Name == nameof(Items) && Items != null) - _viewModel.SetItems(Items); - base.OnPropertyChanged(change); - } - - public class CheckedListBoxViewModel : ViewModelBase - { - public event EventHandler CheckedChanged; - public AvaloniaList CheckboxItems { get; private set; } - - public void SetItems(IEnumerable items) - { - UnsubscribeFromItems(CheckboxItems); - CheckboxItems = new(items.OfType().Select(o => new CheckBoxViewModel { Item = o })); - SubscribeToItems(CheckboxItems); - this.RaisePropertyChanged(nameof(CheckboxItems)); - } - - private void SubscribeToItems(IEnumerable objects) - { - foreach (var i in objects.OfType()) - i.PropertyChanged += I_PropertyChanged; - } - - private void UnsubscribeFromItems(AvaloniaList objects) - { - if (objects is null) return; - - foreach (var i in objects) - i.PropertyChanged -= I_PropertyChanged; - } - private void I_PropertyChanged(object sender, PropertyChangedEventArgs e) - { - CheckedChanged?.Invoke(this, (CheckBoxViewModel)sender); - } - } - public class CheckBoxViewModel : ViewModelBase - { - private bool _isChecked; - public bool IsChecked { get => _isChecked; set => this.RaiseAndSetIfChanged(ref _isChecked, value); } - private object _bookText; - public object Item { get => _bookText; set => this.RaiseAndSetIfChanged(ref _bookText, value); } - } - } - - public class ItemCheckEventArgs : EventArgs - { - public int ItemIndex { get; init; } - public bool IsChecked { get; init; } - public object Item { get; init; } + InitializeComponent(); } } diff --git a/Source/HangoverAvalonia/HangoverAvalonia.csproj b/Source/HangoverAvalonia/HangoverAvalonia.csproj index 2f0ea40d..fd506340 100644 --- a/Source/HangoverAvalonia/HangoverAvalonia.csproj +++ b/Source/HangoverAvalonia/HangoverAvalonia.csproj @@ -76,7 +76,6 @@ - diff --git a/Source/HangoverAvalonia/ViewModels/CheckBoxViewModel.cs b/Source/HangoverAvalonia/ViewModels/CheckBoxViewModel.cs new file mode 100644 index 00000000..f21f62b7 --- /dev/null +++ b/Source/HangoverAvalonia/ViewModels/CheckBoxViewModel.cs @@ -0,0 +1,11 @@ +using ReactiveUI; + +namespace HangoverAvalonia.ViewModels; + +public class CheckBoxViewModel : ViewModelBase +{ + private bool _isChecked; + public bool IsChecked { get => _isChecked; set => this.RaiseAndSetIfChanged(ref _isChecked, value); } + private object _bookText; + public object Item { get => _bookText; set => this.RaiseAndSetIfChanged(ref _bookText, value); } +} diff --git a/Source/LibationAvalonia/Controls/CheckedListBox.axaml b/Source/LibationAvalonia/Controls/CheckedListBox.axaml index 66625cbc..a00ad34d 100644 --- a/Source/LibationAvalonia/Controls/CheckedListBox.axaml +++ b/Source/LibationAvalonia/Controls/CheckedListBox.axaml @@ -5,26 +5,15 @@ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="LibationAvalonia.Controls.CheckedListBox"> - - - - - - - - - - - - - + + + + + + + diff --git a/Source/LibationAvalonia/Controls/CheckedListBox.axaml.cs b/Source/LibationAvalonia/Controls/CheckedListBox.axaml.cs index 7f3d07a5..82d88622 100644 --- a/Source/LibationAvalonia/Controls/CheckedListBox.axaml.cs +++ b/Source/LibationAvalonia/Controls/CheckedListBox.axaml.cs @@ -12,24 +12,10 @@ namespace LibationAvalonia.Controls AvaloniaProperty.Register>(nameof(Items)); public AvaloniaList Items { get => GetValue(ItemsProperty); set => SetValue(ItemsProperty, value); } - private CheckedListBoxViewModel _viewModel = new(); public CheckedListBox() { InitializeComponent(); - scroller.DataContext = _viewModel; - } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) - { - if (change.Property.Name == nameof(Items) && Items != null) - _viewModel.CheckboxItems = Items; - base.OnPropertyChanged(change); - } - - private class CheckedListBoxViewModel : ViewModelBase - { - private AvaloniaList _checkboxItems; - public AvaloniaList CheckboxItems { get => _checkboxItems; set => this.RaiseAndSetIfChanged(ref _checkboxItems, value); } } } diff --git a/Source/LibationAvalonia/LibationAvalonia.csproj b/Source/LibationAvalonia/LibationAvalonia.csproj index 04741857..0696bdb1 100644 --- a/Source/LibationAvalonia/LibationAvalonia.csproj +++ b/Source/LibationAvalonia/LibationAvalonia.csproj @@ -77,7 +77,6 @@ - diff --git a/Source/LibationAvalonia/Views/ProcessQueueControl.axaml b/Source/LibationAvalonia/Views/ProcessQueueControl.axaml index 9418f2c2..faf576e4 100644 --- a/Source/LibationAvalonia/Views/ProcessQueueControl.axaml +++ b/Source/LibationAvalonia/Views/ProcessQueueControl.axaml @@ -10,23 +10,13 @@ Background="{DynamicResource SystemRegionColor}" x:Class="LibationAvalonia.Views.ProcessQueueControl"> - - - - - - - - - - - - - - + @@ -42,14 +32,13 @@ HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" AllowAutoHide="False"> - + + + + + + + From 1a5684799c757fe4c8f5f58ea6bbc6cf80d28150 Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Wed, 7 May 2025 13:12:29 -0600 Subject: [PATCH 7/9] Update Hangover styles and behaviors --- Source/HangoverAvalonia/App.axaml | 29 ++++- .../ViewModels/MainVM.Deleted.cs | 41 +----- .../ViewModels/TrashBinViewModel.cs | 117 ++++++++++++++++++ .../Views/MainWindow.Deleted.cs | 40 +----- .../HangoverAvalonia/Views/MainWindow.axaml | 52 +++++--- .../Views/MainWindow.axaml.cs | 1 - 6 files changed, 191 insertions(+), 89 deletions(-) create mode 100644 Source/HangoverAvalonia/ViewModels/TrashBinViewModel.cs diff --git a/Source/HangoverAvalonia/App.axaml b/Source/HangoverAvalonia/App.axaml index 0534c7e8..6908440c 100644 --- a/Source/HangoverAvalonia/App.axaml +++ b/Source/HangoverAvalonia/App.axaml @@ -6,7 +6,30 @@ - - - + + + + + + + + + + + + + + diff --git a/Source/HangoverAvalonia/ViewModels/MainVM.Deleted.cs b/Source/HangoverAvalonia/ViewModels/MainVM.Deleted.cs index 2c376fd7..827445d0 100644 --- a/Source/HangoverAvalonia/ViewModels/MainVM.Deleted.cs +++ b/Source/HangoverAvalonia/ViewModels/MainVM.Deleted.cs @@ -1,41 +1,8 @@ -using ApplicationServices; -using DataLayer; -using ReactiveUI; -using System.Collections.Generic; +namespace HangoverAvalonia.ViewModels; -namespace HangoverAvalonia.ViewModels +public partial class MainVM { - public partial class MainVM - { - private List _deletedBooks; - public List DeletedBooks { get => _deletedBooks; set => this.RaiseAndSetIfChanged(ref _deletedBooks, value); } - public string CheckedCountText => $"Checked : {_checkedBooksCount} of {_totalBooksCount}"; + public TrashBinViewModel TrashBinViewModel { get; } = new(); - private int _totalBooksCount = 0; - private int _checkedBooksCount = 0; - public int CheckedBooksCount - { - get => _checkedBooksCount; - set - { - if (_checkedBooksCount != value) - { - _checkedBooksCount = value; - this.RaisePropertyChanged(nameof(CheckedCountText)); - } - } - } - private void Load_deletedVM() - { - reload(); - } - - public void reload() - { - DeletedBooks = DbContexts.GetContext().GetDeletedLibraryBooks(); - _checkedBooksCount = 0; - _totalBooksCount = DeletedBooks.Count; - this.RaisePropertyChanged(nameof(CheckedCountText)); - } - } + private void Load_deletedVM() { } } diff --git a/Source/HangoverAvalonia/ViewModels/TrashBinViewModel.cs b/Source/HangoverAvalonia/ViewModels/TrashBinViewModel.cs new file mode 100644 index 00000000..22b5d15b --- /dev/null +++ b/Source/HangoverAvalonia/ViewModels/TrashBinViewModel.cs @@ -0,0 +1,117 @@ +using ApplicationServices; +using Avalonia.Collections; +using DataLayer; +using ReactiveUI; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Threading.Tasks; + +namespace HangoverAvalonia.ViewModels; + +public class TrashBinViewModel : ViewModelBase, IDisposable +{ + public AvaloniaList DeletedBooks { get; } + public string CheckedCountText => $"Checked : {_checkedBooksCount} of {_totalBooksCount}"; + + private bool _controlsEnabled = true; + public bool ControlsEnabled { get => _controlsEnabled; set => this.RaiseAndSetIfChanged(ref _controlsEnabled, value); } + + private bool? everythingChecked = false; + public bool? EverythingChecked + { + get => everythingChecked; + set + { + everythingChecked = value ?? false; + + if (everythingChecked is true) + CheckAll(); + else if (everythingChecked is false) + UncheckAll(); + } + } + + private int _totalBooksCount = 0; + private int _checkedBooksCount = -1; + public int CheckedBooksCount + { + get => _checkedBooksCount; + set + { + _checkedBooksCount = value; + this.RaisePropertyChanged(nameof(CheckedCountText)); + + everythingChecked + = _checkedBooksCount == 0 || _totalBooksCount == 0 ? false + : _checkedBooksCount == _totalBooksCount ? true + : null; + + this.RaisePropertyChanged(nameof(EverythingChecked)); + } + } + + public IEnumerable CheckedBooks => DeletedBooks.Where(i => i.IsChecked).Select(i => i.Item).Cast(); + + public TrashBinViewModel() + { + DeletedBooks = new() + { + ResetBehavior = ResetBehavior.Remove + }; + + tracker = DeletedBooks.TrackItemPropertyChanged(CheckboxPropertyChanged); + Reload(); + } + + public void CheckAll() + { + foreach (var item in DeletedBooks) + item.IsChecked = true; + } + + public void UncheckAll() + { + foreach (var item in DeletedBooks) + item.IsChecked = false; + } + + public async Task RestoreCheckedAsync() + { + ControlsEnabled = false; + var qtyChanges = await Task.Run(CheckedBooks.RestoreBooks); + if (qtyChanges > 0) + Reload(); + ControlsEnabled = true; + } + + public async Task PermanentlyDeleteCheckedAsync() + { + ControlsEnabled = false; + var qtyChanges = await Task.Run(CheckedBooks.PermanentlyDeleteBooks); + if (qtyChanges > 0) + Reload(); + ControlsEnabled = true; + } + + public void Reload() + { + var deletedBooks = DbContexts.GetContext().GetDeletedLibraryBooks(); + + DeletedBooks.Clear(); + DeletedBooks.AddRange(deletedBooks.Select(lb => new CheckBoxViewModel { Item = lb })); + + _totalBooksCount = DeletedBooks.Count; + CheckedBooksCount = 0; + } + + private IDisposable tracker; + private void CheckboxPropertyChanged(Tuple e) + { + if (e.Item2.PropertyName == nameof(CheckBoxViewModel.IsChecked)) + CheckedBooksCount = DeletedBooks.Count(b => b.IsChecked); + } + + public void Dispose() => tracker?.Dispose(); +} diff --git a/Source/HangoverAvalonia/Views/MainWindow.Deleted.cs b/Source/HangoverAvalonia/Views/MainWindow.Deleted.cs index 2c2341e4..101d0375 100644 --- a/Source/HangoverAvalonia/Views/MainWindow.Deleted.cs +++ b/Source/HangoverAvalonia/Views/MainWindow.Deleted.cs @@ -1,40 +1,12 @@ -using ApplicationServices; -using DataLayer; -using HangoverAvalonia.Controls; -using System.Linq; +namespace HangoverAvalonia.Views; -namespace HangoverAvalonia.Views +public partial class MainWindow { - public partial class MainWindow + private void deletedTab_VisibleChanged(bool isVisible) { - private void deletedTab_VisibleChanged(bool isVisible) - { - if (!isVisible) - return; + if (!isVisible) + return; - if (_viewModel.DeletedBooks.Count == 0) - _viewModel.reload(); - } - public void Deleted_CheckedListBox_ItemCheck(object sender, ItemCheckEventArgs args) - { - _viewModel.CheckedBooksCount = deletedCbl.CheckedItems.Count(); - } - public void Deleted_CheckAll_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) - { - foreach (var item in deletedCbl.Items) - deletedCbl.SetItemChecked(item, true); - } - public void Deleted_UncheckAll_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) - { - foreach (var item in deletedCbl.Items) - deletedCbl.SetItemChecked(item, false); - } - public void Deleted_Save_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) - { - var libraryBooksToRestore = deletedCbl.CheckedItems.Cast().ToList(); - var qtyChanges = libraryBooksToRestore.RestoreBooks(); - if (qtyChanges > 0) - _viewModel.reload(); - } + _viewModel.TrashBinViewModel.Reload(); } } diff --git a/Source/HangoverAvalonia/Views/MainWindow.axaml b/Source/HangoverAvalonia/Views/MainWindow.axaml index 1b849ddf..f960db00 100644 --- a/Source/HangoverAvalonia/Views/MainWindow.axaml +++ b/Source/HangoverAvalonia/Views/MainWindow.axaml @@ -15,13 +15,11 @@ - -