Add Last Download column to grid (rmcrackan/Libation#498)

This commit is contained in:
Mbucari 2023-03-02 17:02:27 -07:00
parent bd7e45ca3c
commit d94759d868
12 changed files with 133 additions and 2 deletions

View File

@ -43,6 +43,7 @@ namespace LibationAvalonia.ViewModels
private string _narrators;
private string _category;
private string _misc;
private LastDownloadStatus _lastDownload;
private string _description;
private Rating _productrating;
protected Rating _myRating;
@ -55,6 +56,7 @@ namespace LibationAvalonia.ViewModels
public string Authors { get => _authors; protected set => this.RaiseAndSetIfChanged(ref _authors, value); }
public string Narrators { get => _narrators; protected set => this.RaiseAndSetIfChanged(ref _narrators, value); }
public string Category { get => _category; protected set => this.RaiseAndSetIfChanged(ref _category, value); }
public LastDownloadStatus LastDownload { get => _lastDownload; protected set => this.RaiseAndSetIfChanged(ref _lastDownload, value); }
public string Misc { get => _misc; protected set => this.RaiseAndSetIfChanged(ref _misc, value); }
public string Description { get => _description; protected set => this.RaiseAndSetIfChanged(ref _description, value); }
public Rating ProductRating { get => _productrating; protected set => this.RaiseAndSetIfChanged(ref _productrating, value); }
@ -122,6 +124,7 @@ namespace LibationAvalonia.ViewModels
{ typeof(bool), new ObjectComparer<bool>() },
{ typeof(DateTime), new ObjectComparer<DateTime>() },
{ typeof(LiberateButtonStatus), new ObjectComparer<LiberateButtonStatus>() },
{ typeof(LastDownloadStatus), new ObjectComparer<LastDownloadStatus>() },
};
#endregion

View File

@ -87,6 +87,7 @@ namespace LibationAvalonia.ViewModels
Narrators = Book.NarratorNames();
Category = string.Join(" > ", Book.CategoriesNames());
Misc = GetMiscDisplay(libraryBook);
LastDownload = new(Book.UserDefinedItem);
LongDescription = GetDescriptionDisplay(Book);
Description = TrimTextToWord(LongDescription, 62);
SeriesIndex = Book.SeriesLink.FirstOrDefault()?.Index ?? 0;
@ -127,6 +128,10 @@ namespace LibationAvalonia.ViewModels
_pdfStatus = udi.PdfStatus;
this.RaisePropertyChanged(nameof(Liberate));
break;
case nameof(udi.LastDownloaded):
LastDownload = new(udi);
this.RaisePropertyChanged(nameof(LastDownload));
break;
}
}
@ -149,6 +154,7 @@ namespace LibationAvalonia.ViewModels
{ nameof(Description), () => Description },
{ nameof(Category), () => Category },
{ nameof(Misc), () => Misc },
{ nameof(LastDownload), () => LastDownload },
{ nameof(BookTags), () => BookTags?.Tags ?? string.Empty },
{ nameof(Liberate), () => Liberate },
{ nameof(DateAdded), () => DateAdded },

View File

@ -96,6 +96,7 @@ namespace LibationAvalonia.ViewModels
Narrators = Book.NarratorNames();
Category = string.Join(" > ", Book.CategoriesNames());
Misc = GetMiscDisplay(LibraryBook);
LastDownload = new();
LongDescription = GetDescriptionDisplay(Book);
Description = TrimTextToWord(LongDescription, 62);
@ -124,6 +125,7 @@ namespace LibationAvalonia.ViewModels
{ nameof(Description), () => Description },
{ nameof(Category), () => Category },
{ nameof(Misc), () => Misc },
{ nameof(LastDownload), () => LastDownload },
{ nameof(BookTags), () => BookTags?.Tags ?? string.Empty },
{ nameof(Liberate), () => Liberate },
{ nameof(DateAdded), () => DateAdded },

View File

@ -183,6 +183,16 @@
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</controls:DataGridTemplateColumnExt>
<controls:DataGridTemplateColumnExt Width="102" Header="Last&#xA;Download" CanUserSort="True" SortMemberPath="LastDownload" ClipboardContentBinding="{Binding LastDownload}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Panel Background="{Binding BackgroundBrush}" ToolTip.Tip="{Binding LastDownload.ToolTipText}" DoubleTapped="Version_DoubleClick">
<TextBlock Text="{Binding LastDownload}" TextWrapping="WrapWithOverflow" FontSize="10" />
</Panel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</controls:DataGridTemplateColumnExt>
<controls:DataGridTemplateColumnExt CanUserSort="True" Width="100" Header="Tags" SortMemberPath="BookTags" ClipboardContentBinding="{Binding BookTags.Tags}">
<DataGridTemplateColumn.CellTemplate>

View File

@ -306,6 +306,12 @@ namespace LibationAvalonia.Views
imageDisplayDialog.Close();
}
public void Version_DoubleClick(object sender, Avalonia.Input.TappedEventArgs args)
{
if (sender is Control panel && panel.DataContext is LibraryBookEntry lbe && lbe.LastDownload.IsValid)
lbe.LastDownload.OpenReleaseUrl();
}
public void Cover_Click(object sender, Avalonia.Input.TappedEventArgs args)
{
if (sender is not Image tblock || tblock.DataContext is not GridEntry gEntry)

View File

@ -0,0 +1,41 @@
using DataLayer;
using System;
namespace LibationUiBase
{
public class LastDownloadStatus : IComparable
{
public bool IsValid => LastDownloadedVersion is not null && LastDownloaded.HasValue;
public Version LastDownloadedVersion { get; }
public DateTime? LastDownloaded { get; }
public string ToolTipText => IsValid ? $"Double click to open v{LastDownloadedVersion.ToString(3)} release notes" : "";
public LastDownloadStatus() { }
public LastDownloadStatus(UserDefinedItem udi)
{
LastDownloadedVersion = udi.LastDownloadedVersion;
LastDownloaded = udi.LastDownloaded;
}
public void OpenReleaseUrl()
{
if (IsValid)
Dinah.Core.Go.To.Url($"{AppScaffolding.LibationScaffolding.RepositoryUrl}/releases/tag/v{LastDownloadedVersion.ToString(3)}");
}
public override string ToString()
=> IsValid ? $"{dateString()}\n\nLibation v{LastDownloadedVersion.ToString(3)}" : "";
//Call ToShortDateString to use current culture's date format.
private string dateString() => $"{LastDownloaded.Value.ToShortDateString()} {LastDownloaded.Value:HH:mm}";
public int CompareTo(object obj)
{
if (obj is not LastDownloadStatus second) return -1;
else if (IsValid && !second.IsValid) return -1;
else if (!IsValid && second.IsValid) return 1;
else if (!IsValid && !second.IsValid) return 0;
else return LastDownloaded.Value.CompareTo(second.LastDownloaded.Value);
}
}
}

View File

@ -12,6 +12,6 @@ namespace LibationWinForms.GridView
// per standard INotifyPropertyChanged pattern:
// https://docs.microsoft.com/en-us/dotnet/desktop/wpf/data/how-to-implement-property-change-notification
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
=> this.UIThreadAsync(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
=> this.UIThreadSync(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
}
}

View File

@ -59,6 +59,7 @@ namespace LibationWinForms.GridView
public string Narrators { get; protected set; }
public string Category { get; protected set; }
public string Misc { get; protected set; }
public virtual LastDownloadStatus LastDownload { get; protected set; } = new();
public string Description { get; protected set; }
public string ProductRating { get; protected set; }
protected Rating _myRating;
@ -120,6 +121,7 @@ namespace LibationWinForms.GridView
{ typeof(bool), new ObjectComparer<bool>() },
{ typeof(DateTime), new ObjectComparer<DateTime>() },
{ typeof(LiberateButtonStatus), new ObjectComparer<LiberateButtonStatus>() },
{ typeof(LastDownloadStatus), new ObjectComparer<LastDownloadStatus>() },
};
#endregion

View File

@ -0,0 +1,39 @@
using LibationUiBase;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace LibationWinForms.GridView
{
public class LastDownloadedGridViewColumn : DataGridViewColumn
{
public LastDownloadedGridViewColumn() : base(new LastDownloadedGridViewCell()) { }
public override DataGridViewCell CellTemplate
{
get => base.CellTemplate;
set
{
if (value is not LastDownloadedGridViewCell)
throw new InvalidCastException($"Must be a {nameof(LastDownloadedGridViewCell)}");
base.CellTemplate = value;
}
}
}
internal class LastDownloadedGridViewCell : DataGridViewTextBoxCell
{
private LastDownloadStatus LastDownload => (LastDownloadStatus)Value;
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
ToolTipText = ((LastDownloadStatus)value).ToolTipText;
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
}
protected override void OnDoubleClick(DataGridViewCellEventArgs e)
{
LastDownload.OpenReleaseUrl();
base.OnDoubleClick(e);
}
}
}

View File

@ -1,6 +1,7 @@
using ApplicationServices;
using DataLayer;
using Dinah.Core;
using LibationUiBase;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -24,6 +25,8 @@ namespace LibationWinForms.GridView
private LiberatedStatus _bookStatus;
private LiberatedStatus? _pdfStatus;
public override LastDownloadStatus LastDownload { get; protected set; }
public override RemoveStatus Remove
{
get
@ -87,6 +90,7 @@ namespace LibationWinForms.GridView
Narrators = Book.NarratorNames();
Category = string.Join(" > ", Book.CategoriesNames());
Misc = GetMiscDisplay(libraryBook);
LastDownload = new(Book.UserDefinedItem);
LongDescription = GetDescriptionDisplay(Book);
Description = TrimTextToWord(LongDescription, 62);
SeriesIndex = Book.SeriesLink.FirstOrDefault()?.Index ?? 0;
@ -126,6 +130,10 @@ namespace LibationWinForms.GridView
_pdfStatus = udi.PdfStatus;
NotifyPropertyChanged(nameof(Liberate));
break;
case nameof(udi.LastDownloaded):
LastDownload = new(udi);
NotifyPropertyChanged(nameof(LastDownload));
break;
}
}
@ -153,6 +161,7 @@ namespace LibationWinForms.GridView
{ nameof(Description), () => Description },
{ nameof(Category), () => Category },
{ nameof(Misc), () => Misc },
{ nameof(LastDownload), () => LastDownload },
{ nameof(DisplayTags), () => DisplayTags },
{ nameof(Liberate), () => Liberate },
{ nameof(DateAdded), () => DateAdded },

View File

@ -45,6 +45,7 @@
this.purchaseDateGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.myRatingGVColumn = new LibationWinForms.GridView.MyRatingGridViewColumn();
this.miscGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.lastDownloadedGVColumn = new LastDownloadedGridViewColumn();
this.tagAndDetailsGVColumn = new LibationWinForms.GridView.EditTagsDataGridViewImageButtonColumn();
this.showHideColumnsContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.syncBindingSource = new LibationWinForms.GridView.SyncBindingSource(this.components);
@ -75,7 +76,8 @@
this.purchaseDateGVColumn,
this.myRatingGVColumn,
this.miscGVColumn,
this.tagAndDetailsGVColumn});
this.lastDownloadedGVColumn,
this.tagAndDetailsGVColumn});
this.gridEntryDataGridView.ContextMenuStrip = this.showHideColumnsContextMenuStrip;
this.gridEntryDataGridView.DataSource = this.syncBindingSource;
dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
@ -216,6 +218,15 @@
this.miscGVColumn.ReadOnly = true;
this.miscGVColumn.Width = 135;
//
// lastDownloadedGVColumn
//
this.lastDownloadedGVColumn.DataPropertyName = "LastDownload";
this.lastDownloadedGVColumn.HeaderText = "Last Download";
this.lastDownloadedGVColumn.Name = "lastDownloadedGVColumn";
this.lastDownloadedGVColumn.ReadOnly = true;
this.lastDownloadedGVColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
this.lastDownloadedGVColumn.Width = 108;
//
// tagAndDetailsGVColumn
//
this.tagAndDetailsGVColumn.DataPropertyName = "DisplayTags";
@ -268,6 +279,7 @@
private System.Windows.Forms.DataGridViewTextBoxColumn purchaseDateGVColumn;
private MyRatingGridViewColumn myRatingGVColumn;
private System.Windows.Forms.DataGridViewTextBoxColumn miscGVColumn;
private LastDownloadedGridViewColumn lastDownloadedGVColumn;
private EditTagsDataGridViewImageButtonColumn tagAndDetailsGVColumn;
}
}

View File

@ -122,6 +122,7 @@ namespace LibationWinForms.GridView
{ nameof(Description), () => Description },
{ nameof(Category), () => Category },
{ nameof(Misc), () => Misc },
{ nameof(LastDownload), () => LastDownload },
{ nameof(DisplayTags), () => string.Empty },
{ nameof(Liberate), () => Liberate },
{ nameof(DateAdded), () => DateAdded },