New feature: auto-library updating

This commit is contained in:
Robert McRackan 2022-05-09 15:28:00 -04:00
parent 4332732cc4
commit 6254585ae2
9 changed files with 1053 additions and 980 deletions

View File

@ -36,6 +36,8 @@ New locale options include many more regions including old audible accounts whic
### Import your library
Be default, Libation will periodically scan the accounts you added above with a checkbox next to them. Nothing for you to do. You can also scan manually.
Select Import > Scan Library:
![Import step 1](images/Import1.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<Version>7.2.0.1</Version>
<Version>7.3.0.1</Version>
</PropertyGroup>
<ItemGroup>

View File

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using AudibleApi;
using AudibleUtilities;
using LibationWinForms.Dialogs.Login;
@ -7,6 +8,9 @@ namespace LibationWinForms.Login
{
public class WinformLoginChoiceEager : WinformLoginBase, ILoginChoiceEager
{
/// <summary>Convenience method. Recommended when wiring up Winforms to <see cref="ApplicationServices.LibraryCommands.ImportAccountAsync"/></summary>
public static async Task<ApiExtended> ApiExtendedFunc(Account account) => await ApiExtended.CreateAsync(account, new WinformLoginChoiceEager(account));
public ILoginCallback LoginCallback { get; private set; }
private Account _account { get; }

View File

@ -62,7 +62,7 @@ namespace LibationWinForms.Dialogs
return;
try
{
var removedBooks = await LibraryCommands.FindInactiveBooks((account) => ApiExtended.CreateAsync(account, new WinformLoginChoiceEager(account)), _libraryBooks, _accounts);
var removedBooks = await LibraryCommands.FindInactiveBooks(WinformLoginChoiceEager.ApiExtendedFunc, _libraryBooks, _accounts);
var removable = _removableGridEntries.Where(rge => removedBooks.Any(rb => rb.Book.AudibleProductId == rge.AudibleProductId)).ToList();

File diff suppressed because it is too large Load Diff

View File

@ -27,9 +27,11 @@ namespace LibationWinForms.Dialogs
loggingLevelCb.SelectedItem = config.LogLevel;
}
this.autoScanCb.Text = desc(nameof(config.AutoScan));
this.showImportedStatsCb.Text = desc(nameof(config.ShowImportedStats));
this.importEpisodesCb.Text = desc(nameof(config.ImportEpisodes));
this.downloadEpisodesCb.Text = desc(nameof(config.DownloadEpisodes));
this.booksLocationDescLbl.Text = desc(nameof(config.Books));
this.inProgressDescLbl.Text = desc(nameof(config.InProgress));
this.allowLibationFixupCbox.Text = desc(nameof(config.AllowLibationFixup));
@ -68,6 +70,7 @@ namespace LibationWinForms.Dialogs
LameMatchSourceBRCbox.Checked = config.LameMatchSourceBR;
lameVBRQualityTb.Value = config.LameVBRQuality;
autoScanCb.Checked = config.AutoScan;
showImportedStatsCb.Checked = config.ShowImportedStats;
importEpisodesCb.Checked = config.ImportEpisodes;
downloadEpisodesCb.Checked = config.DownloadEpisodes;
@ -190,6 +193,7 @@ namespace LibationWinForms.Dialogs
config.LameMatchSourceBR = LameMatchSourceBRCbox.Checked;
config.LameVBRQuality = lameVBRQualityTb.Value;
config.AutoScan = autoScanCb.Checked;
config.ShowImportedStats = showImportedStatsCb.Checked;
config.ImportEpisodes = importEpisodesCb.Checked;
config.DownloadEpisodes = downloadEpisodesCb.Checked;

View File

@ -36,6 +36,7 @@
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.noAccountsYetAddAccountToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.autoScanLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.scanLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.scanLibraryOfAllAccountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.scanLibraryOfSomeAccountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@ -57,13 +58,13 @@
this.basicSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.scanningToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.visibleCountLbl = new System.Windows.Forms.ToolStripStatusLabel();
this.springLbl = new System.Windows.Forms.ToolStripStatusLabel();
this.backupsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel();
this.pdfsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel();
this.addFilterBtn = new System.Windows.Forms.Button();
this.scanningToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip1.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.SuspendLayout();
@ -132,6 +133,7 @@
// importToolStripMenuItem
//
this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.autoScanLibraryToolStripMenuItem,
this.noAccountsYetAddAccountToolStripMenuItem,
this.scanLibraryToolStripMenuItem,
this.scanLibraryOfAllAccountsToolStripMenuItem,
@ -148,6 +150,13 @@
this.noAccountsYetAddAccountToolStripMenuItem.Text = "No accounts yet. A&dd Account...";
this.noAccountsYetAddAccountToolStripMenuItem.Click += new System.EventHandler(this.noAccountsYetAddAccountToolStripMenuItem_Click);
//
// autoScanLibraryToolStripMenuItem
//
this.autoScanLibraryToolStripMenuItem.Name = "autoScanLibraryToolStripMenuItem";
this.autoScanLibraryToolStripMenuItem.Size = new System.Drawing.Size(247, 22);
this.autoScanLibraryToolStripMenuItem.Text = "A&uto Scan Library";
this.autoScanLibraryToolStripMenuItem.Click += new System.EventHandler(this.autoScanLibraryToolStripMenuItem_Click);
//
// scanLibraryToolStripMenuItem
//
this.scanLibraryToolStripMenuItem.Name = "scanLibraryToolStripMenuItem";
@ -305,6 +314,16 @@
this.aboutToolStripMenuItem.Text = "A&bout...";
this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
//
// scanningToolStripMenuItem
//
this.scanningToolStripMenuItem.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this.scanningToolStripMenuItem.Enabled = false;
this.scanningToolStripMenuItem.Image = global::LibationWinForms.Properties.Resources.import_16x16;
this.scanningToolStripMenuItem.Name = "scanningToolStripMenuItem";
this.scanningToolStripMenuItem.Size = new System.Drawing.Size(93, 20);
this.scanningToolStripMenuItem.Text = "Scanning...";
this.scanningToolStripMenuItem.Visible = false;
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -354,16 +373,6 @@
this.addFilterBtn.UseVisualStyleBackColor = true;
this.addFilterBtn.Click += new System.EventHandler(this.AddFilterBtn_Click);
//
// scanningToolStripMenuItem
//
this.scanningToolStripMenuItem.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this.scanningToolStripMenuItem.Enabled = false;
this.scanningToolStripMenuItem.Image = global::LibationWinForms.Properties.Resources.import_16x16;
this.scanningToolStripMenuItem.Name = "scanningToolStripMenuItem";
this.scanningToolStripMenuItem.Size = new System.Drawing.Size(93, 20);
this.scanningToolStripMenuItem.Text = "Scanning...";
this.scanningToolStripMenuItem.Visible = false;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
@ -428,5 +437,6 @@
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem scanningToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem autoScanLibraryToolStripMenuItem;
}
}

View File

@ -42,11 +42,7 @@ namespace LibationWinForms
this.Load += refreshImportMenu;
AccountsSettingsPersister.Saved += refreshImportMenu;
// start autoscanner
this.Load += startAutoScan;
AccountsSettingsPersister.Saving += accountsPreSave;
AccountsSettingsPersister.Saved += accountsPostSave;
Configuration.Instance.AutoScanChanged += startAutoScan;
configAndInitAutoScan();
// init default/placeholder cover art
var format = System.Drawing.Imaging.ImageFormat.Jpeg;
@ -55,35 +51,6 @@ namespace LibationWinForms
PictureStorage.SetDefaultImage(PictureSize._500x500, Properties.Resources.default_cover_500x500.ToBytes(format));
}
private List<(string AccountId, string LocaleName)> preSaveDefaultAccounts;
private List<(string AccountId, string LocaleName)> getDefaultAccounts()
{
using var persister = AudibleApiStorage.GetAccountsSettingsPersister();
return persister.AccountsSettings
.GetAll()
.Where(a => a.LibraryScan)
.Select(a => (a.AccountId, a.Locale.Name))
.ToList();
}
private void accountsPreSave(object sender = null, EventArgs e = null)
=> preSaveDefaultAccounts = getDefaultAccounts();
private void accountsPostSave(object sender = null, EventArgs e = null)
{
var postSaveDefaultAccounts = getDefaultAccounts();
var newDefaultAccounts = postSaveDefaultAccounts.Except(preSaveDefaultAccounts).ToList();
if (newDefaultAccounts.Any())
startAutoScan();
}
private void startAutoScan(object sender = null, EventArgs e = null)
{
if (Configuration.Instance.AutoScan)
Console.WriteLine("autoScanner.StartScan();");
else
Console.WriteLine("autoScanner.StopScan();");
}
private void Form1_Load(object sender, EventArgs e)
{
if (this.DesignMode)
@ -275,23 +242,96 @@ namespace LibationWinForms
}
#endregion
#region Auto-scanner
private InterruptableTimer autoScanTimer;
private void configAndInitAutoScan()
{
var hours = 0;
var minutes = 5;
var seconds = 0;
var _5_minutes = new TimeSpan(hours, minutes, seconds);
autoScanTimer = new InterruptableTimer(_5_minutes);
// subscribe as async/non-blocking. I'd actually rather prefer blocking but real-world testing found that caused a deadlock in the AudibleAPI
autoScanTimer.Elapsed += async (_, __) =>
{
using var persister = AudibleApiStorage.GetAccountsSettingsPersister();
var accounts = persister.AccountsSettings
.GetAll()
.Where(a => a.LibraryScan)
.ToArray();
// in autoScan, new books SHALL NOT show dialog
await LibraryCommands.ImportAccountAsync(Login.WinformLoginChoiceEager.ApiExtendedFunc, accounts);
};
// load init state to menu checkbox
this.Load += updateAutoScanLibraryToolStripMenuItem;
// if enabled: begin on load
this.Load += startAutoScan;
// if new 'default' account is added, run autoscan
AccountsSettingsPersister.Saving += accountsPreSave;
AccountsSettingsPersister.Saved += accountsPostSave;
// when autoscan setting is changed, update menu checkbox and run autoscan
Configuration.Instance.AutoScanChanged += updateAutoScanLibraryToolStripMenuItem;
Configuration.Instance.AutoScanChanged += startAutoScan;
}
private List<(string AccountId, string LocaleName)> preSaveDefaultAccounts;
private List<(string AccountId, string LocaleName)> getDefaultAccounts()
{
using var persister = AudibleApiStorage.GetAccountsSettingsPersister();
return persister.AccountsSettings
.GetAll()
.Where(a => a.LibraryScan)
.Select(a => (a.AccountId, a.Locale.Name))
.ToList();
}
private void accountsPreSave(object sender = null, EventArgs e = null)
=> preSaveDefaultAccounts = getDefaultAccounts();
private void accountsPostSave(object sender = null, EventArgs e = null)
{
var postSaveDefaultAccounts = getDefaultAccounts();
var newDefaultAccounts = postSaveDefaultAccounts.Except(preSaveDefaultAccounts).ToList();
if (newDefaultAccounts.Any())
startAutoScan();
}
private void startAutoScan(object sender = null, EventArgs e = null)
{
if (Configuration.Instance.AutoScan)
autoScanTimer.PerformNow();
else
autoScanTimer.Stop();
}
private void updateAutoScanLibraryToolStripMenuItem(object sender, EventArgs e) => autoScanLibraryToolStripMenuItem.Checked = Configuration.Instance.AutoScan;
#endregion
#region Import menu
private void refreshImportMenu(object _ = null, EventArgs __ = null)
{
using var persister = AudibleApiStorage.GetAccountsSettingsPersister();
var count = persister.AccountsSettings.Accounts.Count;
autoScanLibraryToolStripMenuItem.Visible = count > 0;
noAccountsYetAddAccountToolStripMenuItem.Visible = count == 0;
scanLibraryToolStripMenuItem.Visible = count == 1;
scanLibraryOfAllAccountsToolStripMenuItem.Visible = count > 1;
scanLibraryOfSomeAccountsToolStripMenuItem.Visible = count > 1;
removeLibraryBooksToolStripMenuItem.Visible = count != 0;
removeLibraryBooksToolStripMenuItem.Visible = count > 0;
removeSomeAccountsToolStripMenuItem.Visible = count > 1;
removeAllAccountsToolStripMenuItem.Visible = count > 1;
}
private void autoScanLibraryToolStripMenuItem_Click(object sender, EventArgs e) => Configuration.Instance.AutoScan = !autoScanLibraryToolStripMenuItem.Checked;
private void noAccountsYetAddAccountToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("To load your Audible library, come back here to the Import menu after adding your account");
@ -373,7 +413,7 @@ namespace LibationWinForms
{
try
{
var (totalProcessed, newAdded) = await LibraryCommands.ImportAccountAsync(account => ApiExtended.CreateAsync(account, new Login.WinformLoginChoiceEager(account)), accounts);
var (totalProcessed, newAdded) = await LibraryCommands.ImportAccountAsync(Login.WinformLoginChoiceEager.ApiExtendedFunc, accounts);
// this is here instead of ScanEnd so that the following is only possible when it's user-initiated, not automatic loop
if (Configuration.Instance.ShowImportedStats && newAdded > 0)
@ -528,6 +568,6 @@ namespace LibationWinForms
this.scanningToolStripMenuItem.Visible = false;
}
#endregion
}
#endregion
}
}