diff --git a/Images/libation_glass.svg b/Images/libation_glass.svg index d3a0a092..7ecd7089 100644 --- a/Images/libation_glass.svg +++ b/Images/libation_glass.svg @@ -1,28 +1,39 @@ - - - - + + + + + + + + + + + + + diff --git a/Source/DataLayer/EfClasses/Book.cs b/Source/DataLayer/EfClasses/Book.cs index b8bcce6b..01211dc8 100644 --- a/Source/DataLayer/EfClasses/Book.cs +++ b/Source/DataLayer/EfClasses/Book.cs @@ -106,6 +106,7 @@ namespace DataLayer ReplaceAuthors(authors); ReplaceNarrators(narrators); } + public void UpdateTitle(string title, string subtitle) { Title = title?.Trim() ?? ""; @@ -113,8 +114,11 @@ namespace DataLayer _titleWithSubtitle = null; } - #region contributors, authors, narrators - internal HashSet ContributorsLink { get; private set; } + public void UpdateLengthInMinutes(int lengthInMinutes) + => LengthInMinutes = lengthInMinutes; + + #region contributors, authors, narrators + internal HashSet ContributorsLink { get; private set; } public IEnumerable Authors => ContributorsLink.ByRole(Role.Author).Select(bc => bc.Contributor).ToList(); public IEnumerable Narrators => ContributorsLink.ByRole(Role.Narrator).Select(bc => bc.Contributor).ToList(); diff --git a/Source/DtoImporterService/BookImporter.cs b/Source/DtoImporterService/BookImporter.cs index f3813e1c..58eb65f1 100644 --- a/Source/DtoImporterService/BookImporter.cs +++ b/Source/DtoImporterService/BookImporter.cs @@ -149,6 +149,8 @@ namespace DtoImporterService { var item = importItem.DtoItem; + book.UpdateLengthInMinutes(item.LengthInMinutes); + // Update the book titles, since formatting can change book.UpdateTitle(item.Title, item.Subtitle); diff --git a/Source/FileLiberator/AudioFileStorageExt.cs b/Source/FileLiberator/AudioFileStorageExt.cs index e5c2e344..b2eda7cf 100644 --- a/Source/FileLiberator/AudioFileStorageExt.cs +++ b/Source/FileLiberator/AudioFileStorageExt.cs @@ -21,7 +21,8 @@ namespace FileLiberator var series = libraryBook.Book.SeriesLink.SingleOrDefault(); if (series is not null) { - var seriesParent = ApplicationServices.DbContexts.GetContext().GetLibraryBook_Flat_NoTracking(series.Series.AudibleSeriesId); + using var context = ApplicationServices.DbContexts.GetContext(); + var seriesParent = context.GetLibraryBook_Flat_NoTracking(series.Series.AudibleSeriesId); if (seriesParent is not null) { diff --git a/Source/HangoverAvalonia/HangoverAvalonia.csproj b/Source/HangoverAvalonia/HangoverAvalonia.csproj index 435fd2f1..7e213bb4 100644 --- a/Source/HangoverAvalonia/HangoverAvalonia.csproj +++ b/Source/HangoverAvalonia/HangoverAvalonia.csproj @@ -67,13 +67,13 @@ - - + + - - - - + + + + diff --git a/Source/LibationAvalonia/App.axaml b/Source/LibationAvalonia/App.axaml index 6716b9de..c64108d2 100644 --- a/Source/LibationAvalonia/App.axaml +++ b/Source/LibationAvalonia/App.axaml @@ -44,9 +44,9 @@ - - - + + + diff --git a/Source/LibationAvalonia/LibationAvalonia.csproj b/Source/LibationAvalonia/LibationAvalonia.csproj index ee0f9605..e06adfa6 100644 --- a/Source/LibationAvalonia/LibationAvalonia.csproj +++ b/Source/LibationAvalonia/LibationAvalonia.csproj @@ -70,13 +70,13 @@ - - - - - - - + + + + + + + diff --git a/Source/LibationAvalonia/MessageBox.cs b/Source/LibationAvalonia/MessageBox.cs index b5468893..880c3269 100644 --- a/Source/LibationAvalonia/MessageBox.cs +++ b/Source/LibationAvalonia/MessageBox.cs @@ -177,9 +177,12 @@ Libation. tbx.MinWidth = vm.TextBlockMinWidth; tbx.Text = message; - var thisScreen = owner.Screens.ScreenFromVisual(owner); + + var thisScreen = owner.Screens?.ScreenFromVisual(owner); - var maxSize = new Size(0.20 * thisScreen.Bounds.Width, 0.9 * thisScreen.Bounds.Height - 55); + var maxSize + = thisScreen is null ? owner.ClientSize + : new Size(0.20 * thisScreen.Bounds.Width, 0.9 * thisScreen.Bounds.Height - 55); var desiredMax = new Size(maxSize.Width, maxSize.Height); diff --git a/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs b/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs index dec5ca7c..419b387a 100644 --- a/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs +++ b/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs @@ -1,15 +1,18 @@ using ApplicationServices; using AudibleUtilities; using Avalonia.Collections; +using Avalonia.Controls; using Avalonia.Threading; using DataLayer; using LibationAvalonia.Dialogs.Login; +using LibationFileManager; using LibationUiBase.GridView; using ReactiveUI; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading.Tasks; namespace LibationAvalonia.ViewModels @@ -27,8 +30,8 @@ namespace LibationAvalonia.ViewModels public string FilterString { get; private set; } public DataGridCollectionView GridEntries { get; private set; } - private bool _removeColumnVisivle; - public bool RemoveColumnVisivle { get => _removeColumnVisivle; private set => this.RaiseAndSetIfChanged(ref _removeColumnVisivle, value); } + private bool _removeColumnVisible; + public bool RemoveColumnVisible { get => _removeColumnVisible; private set => this.RaiseAndSetIfChanged(ref _removeColumnVisible, value); } public List GetVisibleBookEntries() => FilteredInGridEntries? @@ -321,7 +324,7 @@ namespace LibationAvalonia.ViewModels { foreach (var item in SOURCE) item.PropertyChanged -= GridEntry_PropertyChanged; - RemoveColumnVisivle = false; + RemoveColumnVisible = false; } public async Task RemoveCheckedBooksAsync() @@ -376,7 +379,7 @@ namespace LibationAvalonia.ViewModels item.PropertyChanged += GridEntry_PropertyChanged; } - RemoveColumnVisivle = true; + RemoveColumnVisible = true; RemovableCountChanged?.Invoke(this, 0); try @@ -421,5 +424,44 @@ namespace LibationAvalonia.ViewModels } #endregion + + #region Column Widths + + public DataGridLength TitleWidth { get => getColumnWidth("Title", 200); set => setColumnWidth("Title", value); } + public DataGridLength AuthorsWidth { get => getColumnWidth("Authors", 100); set => setColumnWidth("Authors", value); } + public DataGridLength NarratorsWidth { get => getColumnWidth("Narrators", 100); set => setColumnWidth("Narrators", value); } + public DataGridLength LengthWidth { get => getColumnWidth("Length", 80); set => setColumnWidth("Length", value); } + public DataGridLength SeriesWidth { get => getColumnWidth("Series", 100); set => setColumnWidth("Series", value); } + public DataGridLength SeriesOrderWidth { get => getColumnWidth("SeriesOrder", 60); set => setColumnWidth("SeriesOrder", value); } + public DataGridLength DescriptionWidth { get => getColumnWidth("Description", 100); set => setColumnWidth("Description", value); } + public DataGridLength CategoryWidth { get => getColumnWidth("Category", 100); set => setColumnWidth("Category", value); } + public DataGridLength ProductRatingWidth { get => getColumnWidth("ProductRating", 95); set => setColumnWidth("ProductRating", value); } + public DataGridLength PurchaseDateWidth { get => getColumnWidth("PurchaseDate", 75); set => setColumnWidth("PurchaseDate", value); } + public DataGridLength MyRatingWidth { get => getColumnWidth("MyRating", 95); set => setColumnWidth("MyRating", value); } + public DataGridLength MiscWidth { get => getColumnWidth("Misc", 140); set => setColumnWidth("Misc", value); } + public DataGridLength LastDownloadWidth { get => getColumnWidth("LastDownload", 100); set => setColumnWidth("LastDownload", value); } + public DataGridLength BookTagsWidth { get => getColumnWidth("BookTags", 100); set => setColumnWidth("BookTags", value); } + + private static DataGridLength getColumnWidth(string columnName, double defaultWidth) + => Configuration.Instance.GridColumnsWidths.TryGetValue(columnName, out var val) + ? new DataGridLength(val) + : new DataGridLength(defaultWidth); + + private void setColumnWidth(string columnName, DataGridLength width, [CallerMemberName] string propertyName = "") + { + var dictionary = Configuration.Instance.GridColumnsWidths; + + var newValue = (int)width.DisplayValue; + var valueSame = dictionary.TryGetValue(columnName, out var val) && val == newValue; + dictionary[columnName] = newValue; + + if (!valueSame) + { + Configuration.Instance.GridColumnsWidths = dictionary; + this.RaisePropertyChanged(propertyName); + } + } + + #endregion } } diff --git a/Source/LibationAvalonia/Views/MainWindow.axaml.cs b/Source/LibationAvalonia/Views/MainWindow.axaml.cs index c708258c..a33d95df 100644 --- a/Source/LibationAvalonia/Views/MainWindow.axaml.cs +++ b/Source/LibationAvalonia/Views/MainWindow.axaml.cs @@ -21,7 +21,7 @@ namespace LibationAvalonia.Views InitializeComponent(); Configure_Upgrade(); - Loaded += MainWindow_Loaded; + Opened += MainWindow_Opened; Closing += MainWindow_Closing; LibraryLoaded += MainWindow_LibraryLoaded; @@ -35,7 +35,7 @@ namespace LibationAvalonia.Views } } - private async void MainWindow_Loaded(object sender, EventArgs e) + private async void MainWindow_Opened(object sender, EventArgs e) { if (Configuration.Instance.FirstLaunch) { diff --git a/Source/LibationAvalonia/Views/ProductsDisplay.axaml b/Source/LibationAvalonia/Views/ProductsDisplay.axaml index 4c7e8804..fd90a1c1 100644 --- a/Source/LibationAvalonia/Views/ProductsDisplay.axaml +++ b/Source/LibationAvalonia/Views/ProductsDisplay.axaml @@ -17,6 +17,7 @@ AutoGenerateColumns="False" ItemsSource="{Binding GridEntries}" CanUserSortColumns="True" BorderThickness="3" + CanUserResizeColumns="True" CanUserReorderColumns="True"> @@ -45,10 +46,11 @@ - + - + - + - + - + @@ -98,7 +100,7 @@ - + @@ -108,7 +110,7 @@ - + @@ -118,7 +120,7 @@ - + @@ -128,7 +130,7 @@ - + @@ -138,7 +140,7 @@ - + @@ -148,7 +150,7 @@ - + @@ -158,7 +160,7 @@ - + @@ -172,14 +174,14 @@ x:DataType="uibase:IGridEntry" Header="Product Rating" IsReadOnly="true" - Width="115" + MinWidth="10" Width="{Binding ProductRatingWidth, Mode=TwoWay}" SortMemberPath="ProductRating" CanUserSort="True" OpacityBinding="{CompiledBinding Liberate.Opacity}" BackgroundBinding="{CompiledBinding Liberate.BackgroundBrush}" ClipboardContentBinding="{CompiledBinding ProductRating}" Binding="{CompiledBinding ProductRating}" /> - + @@ -191,16 +193,16 @@ - + @@ -210,7 +212,7 @@ - + @@ -220,7 +222,7 @@ - +