Compare commits

..

14 Commits

Author SHA1 Message Date
Robert
ad5a9874af incr ver 2025-12-02 15:28:59 -05:00
rmcrackan
3b70c08439 Merge pull request #1471 from Mbucari/master
Classic dark mode, customizable downloads, bug fixes
2025-12-02 15:26:24 -05:00
Michael Bucari-Tovo
a230605ed5 Improve GetCounts performance. 2025-12-02 12:43:12 -07:00
Michael Bucari-Tovo
d48ce39773 Move LibraryCommands.GetCounts() to background thread. 2025-12-02 12:30:05 -07:00
Michael Bucari-Tovo
368e695214 Allow users to shoose whether Libation imports Audible Plus titles. 2025-12-02 12:28:16 -07:00
Michael Bucari-Tovo
9c3881c67d Fix LibationCli reusing content licenses (#1473) 2025-12-02 11:09:58 -07:00
MBucari
4c5fdf05f5 Add "Download split by chapters" context menu item (#1436)
All processables are now created with an instance of Configuration, and they use that instance's settings.

Added Configuration.CreateEphemeralCopy() to clone Configuration without persistence.
2025-12-01 23:23:47 -07:00
MBucari
4bd491f5b9 Make winforms book details and search syntax dialogs nonmodal
Match Chardonnay behavior
2025-12-01 21:24:30 -07:00
MBucari
c34b1e752e Update dependencies 2025-12-01 20:40:34 -07:00
MBucari
fa30c10435 Fix PDF validation error (#1470 ) 2025-12-01 20:39:52 -07:00
Michael Bucari-Tovo
cdb91ae2ca Add dark mode to winforms
- Add dark theme icon variants
- Change all light theme icon fill colors to match Chardonnay

Also fixed #1460  by chaing the directory select control to DirectoryOrCustomSelectControl
2025-12-01 20:39:22 -07:00
Robert
7852067b81 incr ver 2025-11-29 23:22:42 -05:00
rmcrackan
3708515df9 Merge pull request #1467 from Mbucari/master
Fix MessageBox launch error on macOS
2025-11-29 23:21:14 -05:00
Mbucari
530aca4f4d Fix MessageBox launch error on macOS 2025-11-29 15:41:38 -07:00
117 changed files with 1944 additions and 1217 deletions

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Version>12.7.4.1</Version>
<Version>12.8.0.1</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Octokit" Version="14.0.0" />

View File

@@ -299,7 +299,7 @@ namespace ApplicationServices
try
{
var dtoItems = await apiExtended.GetLibraryValidatedAsync(libraryOptions, Configuration.Instance.ImportEpisodes);
var dtoItems = await apiExtended.GetLibraryValidatedAsync(libraryOptions);
logTime($"post scanAccountAsync {account.AccountName} qty: {dtoItems.Count}");

View File

@@ -10,6 +10,7 @@ using Dinah.Core;
using Polly;
using Polly.Retry;
using System.Threading;
using LibationFileManager;
#nullable enable
namespace AudibleUtilities
@@ -72,16 +73,16 @@ namespace AudibleUtilities
// 2 retries == 3 total
.RetryAsync(2);
public Task<List<Item>> GetLibraryValidatedAsync(LibraryOptions libraryOptions, bool importEpisodes = true)
public Task<List<Item>> GetLibraryValidatedAsync(LibraryOptions libraryOptions)
{
// bug on audible's side. the 1st time after a long absence, a query to get library will return without titles or authors. a subsequent identical query will be successful. this is true whether or not tokens are refreshed
// worse, this 1st dummy call doesn't seem to help:
// var page = await api.GetLibraryAsync(new AudibleApi.LibraryOptions { NumberOfResultPerPage = 1, PageNumber = 1, PurchasedAfter = DateTime.Now.AddYears(-20), ResponseGroups = AudibleApi.LibraryOptions.ResponseGroupOptions.ALL_OPTIONS });
// i don't want to incur the cost of making a full dummy call every time because it fails sometimes
return policy.ExecuteAsync(() => getItemsAsync(libraryOptions, importEpisodes));
return policy.ExecuteAsync(() => getItemsAsync(libraryOptions));
}
private async Task<List<Item>> getItemsAsync(LibraryOptions libraryOptions, bool importEpisodes)
private async Task<List<Item>> getItemsAsync(LibraryOptions libraryOptions)
{
Serilog.Log.Logger.Debug("Beginning library scan.");
@@ -95,12 +96,12 @@ namespace AudibleUtilities
//Scan the library for all added books.
//Get relationship asins from episode-type items and write them to episodeChannel where they will be batched and queried.
await foreach (var item in Api.GetLibraryItemsPagesAsync(libraryOptions, BatchSize, semaphore))
await foreach (var itemsBatch in Api.GetLibraryItemsPagesAsync(libraryOptions, BatchSize, semaphore))
{
if (importEpisodes)
if (Configuration.Instance.ImportEpisodes)
{
var episodes = item.Where(i => i.IsEpisodes).ToList();
var series = item.Where(i => i.IsSeriesParent).ToList();
var episodes = itemsBatch.Where(i => i.IsEpisodes).ToList();
var series = itemsBatch.Where(i => i.IsSeriesParent).ToList();
var parentAsins = episodes
.SelectMany(i => i.Relationships)
@@ -119,7 +120,11 @@ namespace AudibleUtilities
items.AddRange(series);
}
items.AddRange(item.Where(i => !i.IsSeriesParent && !i.IsEpisodes));
var booksInBatch
= itemsBatch
.Where(i => !i.IsSeriesParent && !i.IsEpisodes)
.Where(i => i.IsAyce is not true || Configuration.Instance.ImportPlusTitles);
items.AddRange(booksInBatch);
}
sw.Stop();

View File

@@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AudibleApi" Version="10.1.0.1" />
<PackageReference Include="AudibleApi" Version="10.1.1.1" />
<PackageReference Include="Google.Protobuf" Version="3.33.1" />
</ItemGroup>

View File

@@ -24,7 +24,7 @@ namespace DataLayer
/// <summary>True if IsLiberated or Error. False if NotLiberated</summary>
public bool AudioExists => book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated or LiberatedStatus.Error;
/// <summary>True if exists and IsLiberated. Else false</summary>
public bool PdfExists => book.UserDefinedItem.PdfStatus == LiberatedStatus.NotLiberated;
public bool PdfExists => book.UserDefinedItem.PdfStatus is LiberatedStatus.Liberated;
/// <summary> Whether the book has any supplements </summary>
public bool HasPdf => book.Supplements.Any();

View File

@@ -16,9 +16,10 @@ namespace FileLiberator
/// Path: directory nested inside of Books directory
/// File name: n/a
/// </summary>
public static string GetDestinationDirectory(this AudioFileStorage _, LibraryBook libraryBook)
public static string GetDestinationDirectory(this AudioFileStorage _, LibraryBook libraryBook, Configuration config = null)
{
if (libraryBook.Book.IsEpisodeChild() && Configuration.Instance.SavePodcastsToParentFolder)
config ??= Configuration.Instance;
if (libraryBook.Book.IsEpisodeChild() && config.SavePodcastsToParentFolder)
{
var series = libraryBook.Book.SeriesLink.SingleOrDefault();
if (series is not null)

View File

@@ -13,7 +13,7 @@ using LibationFileManager;
namespace FileLiberator
{
public class ConvertToMp3 : AudioDecodable
public class ConvertToMp3 : AudioDecodable, IProcessable<ConvertToMp3>
{
public override string Name => "Convert to Mp3";
private Mp4Operation Mp4Operation;
@@ -72,15 +72,14 @@ namespace FileLiberator
OnNarratorsDiscovered(m4bBook.AppleTags.Narrator);
OnCoverImageDiscovered(m4bBook.AppleTags.Cover);
var config = Configuration.Instance;
var lameConfig = DownloadOptions.GetLameOptions(config);
var lameConfig = DownloadOptions.GetLameOptions(Configuration);
var chapters = m4bBook.GetChaptersFromMetadata();
//Finishing configuring lame encoder.
AaxDecrypter.MpegUtil.ConfigureLameOptions(
m4bBook,
lameConfig,
config.LameDownsampleMono,
config.LameMatchSourceBR,
Configuration.LameDownsampleMono,
Configuration.LameMatchSourceBR,
chapters);
if (m4bBook.AppleTags.Tracks is (int trackNum, int trackCount))
@@ -108,9 +107,9 @@ namespace FileLiberator
= FileUtility.SaferMoveToValidPath(
tempPath,
entry.proposedMp3Path,
Configuration.Instance.ReplacementCharacters,
Configuration.ReplacementCharacters,
extension: "mp3",
Configuration.Instance.OverwriteExisting);
Configuration.OverwriteExisting);
SetFileTime(libraryBook, realMp3Path);
SetDirectoryTime(libraryBook, Path.GetDirectoryName(realMp3Path));
@@ -169,5 +168,7 @@ namespace FileLiberator
TotalBytesToReceive = totalInputSize
});
}
public static ConvertToMp3 Create(Configuration config) => new() { Configuration = config };
private ConvertToMp3() { }
}
}

View File

@@ -17,7 +17,7 @@ using System.Threading.Tasks;
#nullable enable
namespace FileLiberator
{
public class DownloadDecryptBook : AudioDecodable
public class DownloadDecryptBook : AudioDecodable, IProcessable<DownloadDecryptBook>
{
public override string Name => "Download & Decrypt";
private CancellationTokenSource? cancellationTokenSource;
@@ -50,8 +50,10 @@ namespace FileLiberator
var api = await libraryBook.GetApiAsync();
LicenseInfo ??= await DownloadOptions.GetDownloadLicenseAsync(api, libraryBook, Configuration.Instance, cancellationToken);
using var downloadOptions = DownloadOptions.BuildDownloadOptions(libraryBook, Configuration.Instance, LicenseInfo);
//Processable instances are reusable, so don't set LicenseInfo
//override from within a DownloadDecryptBook instance.
var license = LicenseInfo ?? await DownloadOptions.GetDownloadLicenseAsync(api, libraryBook, Configuration, cancellationToken);
using var downloadOptions = DownloadOptions.BuildDownloadOptions(libraryBook, Configuration, license);
var result = await DownloadAudiobookAsync(api, downloadOptions, cancellationToken);
if (!result.Success || getFirstAudioFile(result.ResultFiles) is not TempFile audioFile)
@@ -62,7 +64,7 @@ namespace FileLiberator
return new StatusHandler { "Decrypt failed" };
}
if (Configuration.Instance.RetainAaxFile)
if (Configuration.RetainAaxFile)
{
//Add the cached aaxc and key files to the entries list to be moved to the Books directory.
result.ResultFiles.AddRange(getAaxcFiles(result.CacheFiles));
@@ -256,7 +258,7 @@ namespace FileLiberator
private void AaxcDownloader_RetrievedCoverArt(object? sender, byte[]? e)
{
if (Configuration.Instance.AllowLibationFixup && sender is AaxcDownloadConvertBase downloader)
if (Configuration.AllowLibationFixup && sender is AaxcDownloadConvertBase downloader)
{
try
{
@@ -345,15 +347,15 @@ namespace FileLiberator
destinationDir,
entry.Extension,
entry.PartProperties,
Configuration.Instance.OverwriteExisting);
Configuration.OverwriteExisting);
var realDest
= FileUtility.SaferMoveToValidPath(
entry.FilePath,
destFileName,
Configuration.Instance.ReplacementCharacters,
Configuration.ReplacementCharacters,
entry.Extension,
Configuration.Instance.OverwriteExisting);
Configuration.OverwriteExisting);
#region File Move Progress
totalBytesMoved += new FileInfo(realDest).Length;
@@ -403,7 +405,7 @@ namespace FileLiberator
options.LibraryBook,
destinationDir,
extension: ".jpg",
returnFirstExisting: Configuration.Instance.OverwriteExisting);
returnFirstExisting: Configuration.OverwriteExisting);
if (File.Exists(coverPath))
FileUtility.SaferDelete(coverPath);
@@ -440,7 +442,7 @@ namespace FileLiberator
options.LibraryBook,
destinationDir,
extension: formatExtension,
returnFirstExisting: Configuration.Instance.OverwriteExisting);
returnFirstExisting: Configuration.OverwriteExisting);
if (File.Exists(recordsPath))
FileUtility.SaferDelete(recordsPath);
@@ -487,7 +489,7 @@ namespace FileLiberator
options.LibraryBook,
destinationDir,
extension: ".metadata.json",
returnFirstExisting: Configuration.Instance.OverwriteExisting);
returnFirstExisting: Configuration.OverwriteExisting);
if (File.Exists(metadataPath))
FileUtility.SaferDelete(metadataPath);
@@ -512,10 +514,10 @@ namespace FileLiberator
#endregion
#region Macros
private static string getDestinationDirectory(LibraryBook libraryBook)
private string getDestinationDirectory(LibraryBook libraryBook)
{
Serilog.Log.Verbose("Getting destination directory for {@Book}", libraryBook.LogFriendly());
var destinationDir = AudibleFileStorage.Audio.GetDestinationDirectory(libraryBook);
var destinationDir = AudibleFileStorage.Audio.GetDestinationDirectory(libraryBook, Configuration);
Serilog.Log.Verbose("Got destination directory for {@Book}. {@Directory}", libraryBook.LogFriendly(), destinationDir);
if (!Directory.Exists(destinationDir))
{
@@ -533,5 +535,8 @@ namespace FileLiberator
private static IEnumerable<TempFile> getAaxcFiles(IEnumerable<TempFile> entries)
=> entries.Where(f => File.Exists(f.FilePath) && (getFileType(f) is FileType.AAXC || f.Extension.Equals(".key", StringComparison.OrdinalIgnoreCase)));
#endregion
public static DownloadDecryptBook Create(Configuration config) => new() { Configuration = config };
private DownloadDecryptBook() { }
}
}

View File

@@ -13,7 +13,7 @@ using LibationFileManager;
namespace FileLiberator
{
public class DownloadPdf : Processable
public class DownloadPdf : Processable, IProcessable<DownloadPdf>
{
public override string Name => "Download Pdf";
public override bool Validate(LibraryBook libraryBook)
@@ -89,5 +89,8 @@ namespace FileLiberator
=> !File.Exists(actualDownloadedFilePath)
? new StatusHandler { "Downloaded PDF cannot be found" }
: new StatusHandler();
public static DownloadPdf Create(Configuration config) => new() { Configuration = config };
private DownloadPdf() { }
}
}

View File

@@ -9,24 +9,36 @@ using Dinah.Core.ErrorHandling;
using Dinah.Core.Net.Http;
using LibationFileManager;
#nullable enable
namespace FileLiberator
{
public abstract class Processable
public interface IProcessable<T> where T : IProcessable<T>
{
/// <summary>
/// Create a new instance of the Processable which uses a specific Configuration
/// </summary>
/// <param name="config">The <see cref="Configuration"/> this <typeparamref name="T"/> will use</param>
static abstract T Create(Configuration config);
}
public abstract class Processable
{
public abstract string Name { get; }
public event EventHandler<LibraryBook> Begin;
public event EventHandler<LibraryBook>? Begin;
/// <summary>General string message to display. DON'T rely on this for success, failure, or control logic</summary>
public event EventHandler<string> StatusUpdate;
public event EventHandler<string>? StatusUpdate;
/// <summary>Fired when a file is successfully saved to disk</summary>
public event EventHandler<(string id, string path)> FileCreated;
public event EventHandler<DownloadProgress> StreamingProgressChanged;
public event EventHandler<TimeSpan> StreamingTimeRemaining;
public event EventHandler<(string id, string path)>? FileCreated;
public event EventHandler<DownloadProgress>? StreamingProgressChanged;
public event EventHandler<TimeSpan>? StreamingTimeRemaining;
public event EventHandler<LibraryBook> Completed;
public event EventHandler<LibraryBook>? Completed;
/// <returns>True == Valid</returns>
public abstract bool Validate(LibraryBook libraryBook);
public required Configuration Configuration{ get; init; }
protected Processable() { }
/// <returns>True == Valid</returns>
public abstract bool Validate(LibraryBook libraryBook);
/// <returns>True == success</returns>
public abstract Task<StatusHandler> ProcessAsync(LibraryBook libraryBook);
@@ -35,7 +47,7 @@ namespace FileLiberator
public IEnumerable<LibraryBook> GetValidLibraryBooks(IEnumerable<LibraryBook> library)
=> library.Where(libraryBook =>
Validate(libraryBook)
&& (!libraryBook.Book.IsEpisodeChild() || Configuration.Instance.DownloadEpisodes)
&& (!libraryBook.Book.IsEpisodeChild() || Configuration.DownloadEpisodes)
);
public async Task<StatusHandler> ProcessSingleAsync(LibraryBook libraryBook, bool validate)
@@ -86,12 +98,12 @@ namespace FileLiberator
protected void OnStreamingProgressChanged(DownloadProgress progress)
=> OnStreamingProgressChanged(null, progress);
protected void OnStreamingProgressChanged(object _, DownloadProgress progress)
protected void OnStreamingProgressChanged(object? _, DownloadProgress progress)
=> StreamingProgressChanged?.Invoke(this, progress);
protected void OnStreamingTimeRemaining(TimeSpan timeRemaining)
=> OnStreamingTimeRemaining(null, timeRemaining);
protected void OnStreamingTimeRemaining(object _, TimeSpan timeRemaining)
protected void OnStreamingTimeRemaining(object? _, TimeSpan timeRemaining)
=> StreamingTimeRemaining?.Invoke(this, timeRemaining);
protected void OnCompleted(LibraryBook libraryBook)
@@ -100,17 +112,17 @@ namespace FileLiberator
Completed?.Invoke(this, libraryBook);
}
protected static void SetFileTime(LibraryBook libraryBook, string file)
protected void SetFileTime(LibraryBook libraryBook, string file)
=> setFileSystemTime(libraryBook, new FileInfo(file));
protected static void SetDirectoryTime(LibraryBook libraryBook, string file)
protected void SetDirectoryTime(LibraryBook libraryBook, string file)
=> setFileSystemTime(libraryBook, new DirectoryInfo(file));
private static void setFileSystemTime(LibraryBook libraryBook, FileSystemInfo fileInfo)
private void setFileSystemTime(LibraryBook libraryBook, FileSystemInfo fileInfo)
{
if (!fileInfo.Exists) return;
fileInfo.CreationTimeUtc = getTimeValue(Configuration.Instance.CreationTime) ?? fileInfo.CreationTimeUtc;
fileInfo.LastWriteTimeUtc = getTimeValue(Configuration.Instance.LastWriteTime) ?? fileInfo.LastWriteTimeUtc;
fileInfo.CreationTimeUtc = getTimeValue(Configuration.CreationTime) ?? fileInfo.CreationTimeUtc;
fileInfo.LastWriteTimeUtc = getTimeValue(Configuration.LastWriteTime) ?? fileInfo.LastWriteTimeUtc;
DateTime? getTimeValue(Configuration.DateTimeSource source) => source switch
{

View File

@@ -6,7 +6,7 @@
<ItemGroup>
<PackageReference Include="Dinah.Core" Version="10.0.0.1" />
<PackageReference Include="Polly" Version="8.6.4" />
<PackageReference Include="Polly" Version="8.6.5" />
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@@ -7,6 +7,7 @@ namespace FileManager;
public interface IJsonBackedDictionary
{
JObject GetJObject();
bool Exists(string propertyName);
string? GetString(string propertyName, string? defaultValue = null);
T? GetNonString<T>(string propertyName, T? defaultValue = default);

View File

@@ -273,5 +273,7 @@ namespace FileManager
{
File.WriteAllText(Filepath, "{}");
}
}
public JObject GetJObject() => readFile();
}
}

View File

@@ -136,12 +136,12 @@ public class App : Application
[PropertyChangeFilter(nameof(ThemeVariant))]
private static void ThemeVariant_PropertyChanged(object sender, PropertyChangedEventArgsEx e)
=> OpenAndApplyTheme(e.NewValue as string);
=> OpenAndApplyTheme(e.NewValue as Configuration.Theme? ?? Configuration.Theme.System);
private static void OnActualThemeVariantChanged(object? sender, EventArgs e)
=> OpenAndApplyTheme(Configuration.Instance.GetString(propertyName: nameof(ThemeVariant)));
=> OpenAndApplyTheme(Configuration.Instance.ThemeVariant);
private static void OpenAndApplyTheme(string? themeVariant)
private static void OpenAndApplyTheme(Configuration.Theme themeVariant)
{
using ChardonnayThemePersister? themePersister = ChardonnayThemePersister.Create();
themePersister?.Target.ApplyTheme(themeVariant);

View File

@@ -30,6 +30,10 @@
<TextBlock Text="{CompiledBinding ImportEpisodesText}" />
</CheckBox>
<CheckBox IsChecked="{CompiledBinding ImportPlusTitles, Mode=TwoWay}">
<TextBlock Text="{CompiledBinding ImportPlusTitlesText}" />
</CheckBox>
<CheckBox IsChecked="{CompiledBinding DownloadEpisodes, Mode=TwoWay}">
<TextBlock Text="{CompiledBinding DownloadEpisodesText}" />
</CheckBox>

View File

@@ -52,7 +52,8 @@ namespace LibationAvalonia.Controls.Settings
var parent = ThemeComboBox.Parent as Panel;
if (parent?.Children.Remove(ThemeComboBox) ?? false)
{
Configuration.Instance.SetString(ViewModel?.ThemeVariant, nameof(ViewModel.ThemeVariant));
Configuration.Instance.ThemeVariant = ViewModel?.ThemeVariant.Value ?? Configuration.Theme.System;
parent.Children.Add(ThemeComboBox);
}
ThemeComboBox.SelectionChanged += ThemeComboBox_SelectionChanged;

View File

@@ -2,6 +2,7 @@ using Avalonia.Controls;
using DataLayer;
using Dinah.Core.ErrorHandling;
using LibationAvalonia.ViewModels;
using LibationFileManager;
using LibationUiBase.ProcessQueue;
using System.Collections.Generic;
using System.Linq;
@@ -32,11 +33,11 @@ public partial class ThemePreviewControl : UserControl
MainVM.Configure_NonUI();
}
QueuedBook = new ProcessBookViewModel(sampleEntries[0]) { Status = ProcessBookStatus.Queued };
WorkingBook = new ProcessBookViewModel(sampleEntries[0]) { Status = ProcessBookStatus.Working };
CompletedBook = new ProcessBookViewModel(sampleEntries[0]) { Status = ProcessBookStatus.Completed };
CancelledBook = new ProcessBookViewModel(sampleEntries[0]) { Status = ProcessBookStatus.Cancelled };
FailedBook = new ProcessBookViewModel(sampleEntries[0]) { Status = ProcessBookStatus.Failed };
QueuedBook = new ProcessBookViewModel(sampleEntries[0], Configuration.Instance) { Status = ProcessBookStatus.Queued };
WorkingBook = new ProcessBookViewModel(sampleEntries[0], Configuration.Instance) { Status = ProcessBookStatus.Working };
CompletedBook = new ProcessBookViewModel(sampleEntries[0], Configuration.Instance) { Status = ProcessBookStatus.Completed };
CancelledBook = new ProcessBookViewModel(sampleEntries[0], Configuration.Instance) { Status = ProcessBookStatus.Cancelled };
FailedBook = new ProcessBookViewModel(sampleEntries[0], Configuration.Instance) { Status = ProcessBookStatus.Failed };
//Set the current processable so that the empty queue doesn't try to advance.
QueuedBook.AddDownloadPdf();

View File

@@ -29,11 +29,11 @@ namespace LibationAvalonia.Dialogs
if (Design.IsDesignMode)
{
var themeVariant = Configuration.CreateMockInstance().GetString(propertyName: nameof(ThemeVariant));
var themeVariant = Configuration.CreateMockInstance().ThemeVariant;
RequestedThemeVariant = themeVariant switch
{
nameof(ThemeVariant.Dark) => ThemeVariant.Dark,
nameof(ThemeVariant.Light) => ThemeVariant.Light,
Configuration.Theme.Dark => ThemeVariant.Dark,
Configuration.Theme.Light => ThemeVariant.Light,
_ => ThemeVariant.Default,
};
}

View File

@@ -11,10 +11,11 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Platform;
#nullable enable
namespace LibationAvalonia
{
public class MessageBox
{
public static Task<DialogResult> Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
@@ -27,15 +28,15 @@ namespace LibationAvalonia
=> ShowCoreAsync(null, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
public static Task<DialogResult> Show(string text)
=> ShowCoreAsync(null, text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
public static Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
public static Task<DialogResult> Show(Window? owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
=> ShowCoreAsync(owner, text, caption, buttons, icon, defaultButton, saveAndRestorePosition);
public static Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
public static Task<DialogResult> Show(Window? owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
=> ShowCoreAsync(owner, text, caption, buttons, icon, MessageBoxDefaultButton.Button1);
public static Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons)
public static Task<DialogResult> Show(Window? owner, string text, string caption, MessageBoxButtons buttons)
=> ShowCoreAsync(owner, text, caption, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
public static Task<DialogResult> Show(Window owner, string text, string caption)
public static Task<DialogResult> Show(Window? owner, string text, string caption)
=> ShowCoreAsync(owner, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
public static Task<DialogResult> Show(Window owner, string text)
public static Task<DialogResult> Show(Window? owner, string text)
=> ShowCoreAsync(owner, text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
public static async Task VerboseLoggingWarning_ShowIfTrue()
@@ -58,7 +59,7 @@ namespace LibationAvalonia
/// <summary>
/// Note: the format field should use {0} and NOT use the `$` string interpolation. Formatting is done inside this method.
/// </summary>
public static async Task<DialogResult> ShowConfirmationDialog(Window owner, IEnumerable<LibraryBook> libraryBooks, string format, string title, MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1)
public static async Task<DialogResult> ShowConfirmationDialog(Window? owner, IEnumerable<LibraryBook> libraryBooks, string format, string title, MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1)
{
if (libraryBooks is null || !libraryBooks.Any())
return DialogResult.Cancel;
@@ -88,7 +89,7 @@ namespace LibationAvalonia
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <param name="exception">Exception to log.</param>
public static async Task ShowAdminAlert(Window owner, string text, string caption, Exception exception)
public static async Task ShowAdminAlert(Window? owner, string text, string caption, Exception exception)
{
// for development and debugging, show me what broke!
if (System.Diagnostics.Debugger.IsAttached)
@@ -106,7 +107,7 @@ namespace LibationAvalonia
await DisplayWindow(form, owner);
}
private static async Task<DialogResult> ShowCoreAsync(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
private static async Task<DialogResult> ShowCoreAsync(Window? owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
=> await Dispatcher.UIThread.InvokeAsync(async () =>
{
owner = owner?.IsLoaded is true ? owner : null;
@@ -114,10 +115,8 @@ namespace LibationAvalonia
return await DisplayWindow(dialog, owner);
});
private static MessageBoxWindow CreateMessageBox(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
private static MessageBoxWindow CreateMessageBox(Window? owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
{
owner ??= (Application.Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime).MainWindow;
var dialog = new MessageBoxWindow(saveAndRestorePosition);
var vm = new MessageBoxViewModel(message, caption, buttons, icon, defaultButton);
@@ -125,18 +124,12 @@ namespace LibationAvalonia
dialog.ControlToFocusOnShow = dialog.FindControl<Control>(defaultButton.ToString());
dialog.CanResize = false;
dialog.WindowStartupLocation = WindowStartupLocation.CenterOwner;
var tbx = dialog.FindControl<TextBlock>("messageTextBlock");
var tbx = dialog.messageTextBlock;
tbx.MinWidth = vm.TextBlockMinWidth;
tbx.Text = message;
var thisScreen = owner.Screens?.ScreenFromVisual(owner);
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);
var desiredMax = GetMaxMessageBoxSizeFromOwner(owner);
tbx.Measure(desiredMax);
@@ -152,13 +145,34 @@ namespace LibationAvalonia
dialog.Width = dialog.MinWidth;
return dialog;
}
private static async Task<DialogResult> DisplayWindow(DialogWindow toDisplay, Window owner)
private static Size GetMaxMessageBoxSizeFromOwner(TopLevel? owner)
{
if (owner is null && App.Current is IClassicDesktopStyleApplicationLifetime lt)
{
//The Windows enumeration will only contain active (non-disposed) windows.
//If none are available, the last disposed window may still be in MainWindow
//Just be careful what you use it for. It will still have Screens, but
//ScreenFromTopLevel can't be used on macOS.
owner = lt.Windows.FirstOrDefault() ?? lt.MainWindow;
}
if (owner?.Screens is Screens screens)
{
var mainScreen = owner?.PlatformImpl is null ? screens.Primary : screens.ScreenFromTopLevel(owner);
if (mainScreen is not null)
return new Size(0.20 * mainScreen.Bounds.Width, 0.9 * mainScreen.Bounds.Height - 55);
}
return owner?.ClientSize ?? new Size(800, 600);
}
private static async Task<DialogResult> DisplayWindow(DialogWindow toDisplay, Window? owner)
{
if (owner is null)
{
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
if (desktop.MainWindow.IsLoaded)
if (desktop.MainWindow?.IsLoaded is true)
return await toDisplay.ShowDialog<DialogResult>(desktop.MainWindow);
else
{
@@ -185,7 +199,6 @@ namespace LibationAvalonia
window.Close();
return result;
}
}
else
{

View File

@@ -37,7 +37,7 @@ public class ChardonnayTheme : IUpdatable, ICloneable
/// <summary> Invoke <see cref="IUpdatable.Updated"/> </summary>
public void Save() => Updated?.Invoke(this, EventArgs.Empty);
public Color GetColor(string? themeVariant, string itemName)
public Color GetColor(LibationFileManager.Configuration.Theme themeVariant, string itemName)
=> GetColor(FromVariantName(themeVariant), itemName);
public Color GetColor(ThemeVariant themeVariant, string itemName)
@@ -46,7 +46,7 @@ public class ChardonnayTheme : IUpdatable, ICloneable
return ThemeColors[themeVariant].TryGetValue(itemName, out var color) ? color : default;
}
public ChardonnayTheme SetColor(string? themeVariant, Expression<Func<ColorPaletteResources, Color>> colorSelector, Color color)
public ChardonnayTheme SetColor(LibationFileManager.Configuration.Theme themeVariant, Expression<Func<ColorPaletteResources, Color>> colorSelector, Color color)
=> SetColor(FromVariantName(themeVariant), colorSelector, color);
public ChardonnayTheme SetColor(ThemeVariant themeVariant, Expression<Func<ColorPaletteResources, Color>> colorSelector, Color color)
@@ -59,7 +59,7 @@ public class ChardonnayTheme : IUpdatable, ICloneable
return this;
}
public ChardonnayTheme SetColor(string? themeVariant, string itemName, Color itemColor)
public ChardonnayTheme SetColor(LibationFileManager.Configuration.Theme themeVariant, string itemName, Color itemColor)
=> SetColor(FromVariantName(themeVariant), itemName, itemColor);
public ChardonnayTheme SetColor(ThemeVariant themeVariant, string itemName, Color itemColor)
@@ -69,7 +69,7 @@ public class ChardonnayTheme : IUpdatable, ICloneable
return this;
}
public FrozenDictionary<string, Color> GetThemeColors(string? themeVariant)
public FrozenDictionary<string, Color> GetThemeColors(LibationFileManager.Configuration.Theme themeVariant)
=> GetThemeColors(FromVariantName(themeVariant));
public FrozenDictionary<string, Color> GetThemeColors(ThemeVariant themeVariant)
@@ -78,7 +78,7 @@ public class ChardonnayTheme : IUpdatable, ICloneable
return ThemeColors[themeVariant].ToFrozenDictionary();
}
public void ApplyTheme(string? themeVariant)
public void ApplyTheme(LibationFileManager.Configuration.Theme themeVariant)
=> ApplyTheme(FromVariantName(themeVariant));
public void ApplyTheme(ThemeVariant themeVariant)
@@ -195,11 +195,11 @@ public class ChardonnayTheme : IUpdatable, ICloneable
throw new InvalidOperationException("FluentTheme.Palettes only supports Light and Dark variants.");
}
private static ThemeVariant FromVariantName(string? variantName)
private static ThemeVariant FromVariantName(LibationFileManager.Configuration.Theme variantName)
=> variantName switch
{
nameof(ThemeVariant.Dark) => ThemeVariant.Dark,
nameof(ThemeVariant.Light) => ThemeVariant.Light,
LibationFileManager.Configuration.Theme.Dark => ThemeVariant.Dark,
LibationFileManager.Configuration.Theme.Light => ThemeVariant.Light,
// "System"
_ => ThemeVariant.Default
};

View File

@@ -32,13 +32,13 @@ namespace LibationAvalonia.ViewModels
setQueueCollapseState(collapseState);
}
public async void LiberateClicked(LibraryBook[] libraryBooks)
public async void LiberateClicked(System.Collections.Generic.IList<LibraryBook> libraryBooks, Configuration config)
{
try
{
if (ProcessQueue.QueueDownloadDecrypt(libraryBooks))
if (ProcessQueue.QueueDownloadDecrypt(libraryBooks, config))
setQueueCollapseState(false);
else if (libraryBooks.Length == 1 && libraryBooks[0].Book.AudioExists)
else if (libraryBooks.Count == 1 && libraryBooks[0].Book.AudioExists)
{
// liberated: open explorer to file
var filePath = AudibleFileStorage.Audio.GetPath(libraryBooks[0].Book.AudibleProductId);

View File

@@ -63,11 +63,11 @@ namespace LibationAvalonia.ViewModels
public async void ProductsDisplay_VisibleCountChanged(object? sender, int qty)
{
setVisibleCount(qty);
await Dispatcher.UIThread.InvokeAsync(setLiberatedVisibleMenuItem);
await setLiberatedVisibleMenuItemAsync();
}
private async void setLiberatedVisibleMenuItemAsync(object? _, object __)
=> await Dispatcher.UIThread.InvokeAsync(setLiberatedVisibleMenuItem);
=> await setLiberatedVisibleMenuItemAsync();
public void LiberateVisible()
@@ -191,10 +191,11 @@ namespace LibationAvalonia.ViewModels
await visibleLibraryBooks.RemoveBooksAsync();
}
private void setLiberatedVisibleMenuItem()
private async Task setLiberatedVisibleMenuItemAsync()
{
var libraryStats = LibraryCommands.GetCounts(ProductsDisplay.GetVisibleBookEntries());
setVisibleNotLiberatedCount(libraryStats.PendingBooks);
var visible = ProductsDisplay.GetVisibleBookEntries();
var libraryStats = await Task.Run(() => LibraryCommands.GetCounts(visible));
await Dispatcher.UIThread.InvokeAsync(() => setVisibleNotLiberatedCount(libraryStats.PendingBooks));
}
}
}

View File

@@ -10,6 +10,7 @@ namespace LibationAvalonia.ViewModels.Settings
AutoScan = config.AutoScan;
ShowImportedStats = config.ShowImportedStats;
ImportEpisodes = config.ImportEpisodes;
ImportPlusTitles = config.ImportPlusTitles;
DownloadEpisodes = config.DownloadEpisodes;
AutoDownloadEpisodes = config.AutoDownloadEpisodes;
}
@@ -19,6 +20,7 @@ namespace LibationAvalonia.ViewModels.Settings
config.AutoScan = AutoScan;
config.ShowImportedStats = ShowImportedStats;
config.ImportEpisodes = ImportEpisodes;
config.ImportPlusTitles = ImportPlusTitles;
config.DownloadEpisodes = DownloadEpisodes;
config.AutoDownloadEpisodes = AutoDownloadEpisodes;
}
@@ -26,12 +28,14 @@ namespace LibationAvalonia.ViewModels.Settings
public string AutoScanText { get; } = Configuration.GetDescription(nameof(Configuration.AutoScan));
public string ShowImportedStatsText { get; } = Configuration.GetDescription(nameof(Configuration.ShowImportedStats));
public string ImportEpisodesText { get; } = Configuration.GetDescription(nameof(Configuration.ImportEpisodes));
public string ImportPlusTitlesText { get; } = Configuration.GetDescription(nameof(Configuration.ImportPlusTitles));
public string DownloadEpisodesText { get; } = Configuration.GetDescription(nameof(Configuration.DownloadEpisodes));
public string AutoDownloadEpisodesText { get; } = Configuration.GetDescription(nameof(Configuration.AutoDownloadEpisodes));
public bool AutoScan { get; set; }
public bool ShowImportedStats { get; set; }
public bool ImportEpisodes { get; set; }
public bool ImportPlusTitles { get; set; }
public bool DownloadEpisodes { get; set; }
public bool AutoDownloadEpisodes { get; set; }
}

View File

@@ -12,8 +12,7 @@ namespace LibationAvalonia.ViewModels.Settings
{
public class ImportantSettingsVM : ViewModelBase
{
private string themeVariant;
private string initialThemeVariant;
private EnumDisplay<Configuration.Theme> themeVariant;
private readonly Configuration config;
public ImportantSettingsVM(Configuration config)
@@ -30,9 +29,7 @@ namespace LibationAvalonia.ViewModels.Settings
GridScaleFactor = scaleFactorToLinearRange(config.GridScaleFactor);
GridFontScaleFactor = scaleFactorToLinearRange(config.GridFontScaleFactor);
themeVariant = initialThemeVariant = config.GetString(propertyName: nameof(ThemeVariant)) ?? "";
if (string.IsNullOrWhiteSpace(initialThemeVariant))
themeVariant = initialThemeVariant = "System";
themeVariant = Themes.Single(v => v.Value == config.ThemeVariant);
}
public void SaveSettings(Configuration config)
@@ -91,7 +88,10 @@ namespace LibationAvalonia.ViewModels.Settings
public string GridScaleFactorText { get; } = Configuration.GetDescription(nameof(Configuration.GridScaleFactor));
public string GridFontScaleFactorText { get; } = Configuration.GetDescription(nameof(Configuration.GridFontScaleFactor));
public string BetaOptInText { get; } = Configuration.GetDescription(nameof(Configuration.BetaOptIn));
public string[] Themes { get; } = { "System", nameof(Avalonia.Styling.ThemeVariant.Light), nameof(Avalonia.Styling.ThemeVariant.Dark) };
public EnumDisplay<Configuration.Theme>[] Themes { get; }
= Enum.GetValues<Configuration.Theme>()
.Select(v => new EnumDisplay<Configuration.Theme>(v))
.ToArray();
public string BooksDirectory { get; set; }
public bool SavePodcastsToParentFolder { get; set; }
@@ -103,7 +103,7 @@ namespace LibationAvalonia.ViewModels.Settings
public bool UseWebView { get; set; }
public Serilog.Events.LogEventLevel LoggingLevel { get; set; }
public string ThemeVariant
public EnumDisplay<Configuration.Theme> ThemeVariant
{
get => themeVariant;
set => this.RaiseAndSetIfChanged(ref themeVariant, value);

View File

@@ -173,7 +173,7 @@ namespace LibationAvalonia.Views
await ViewModel.BindToGridTask;
}
public void ProductsDisplay_LiberateClicked(object _, LibraryBook[] libraryBook) => ViewModel.LiberateClicked(libraryBook);
public void ProductsDisplay_LiberateClicked(object _, IList<LibraryBook> libraryBook, Configuration config) => ViewModel.LiberateClicked(libraryBook, config);
public void ProductsDisplay_LiberateSeriesClicked(object _, SeriesEntry series) => ViewModel.LiberateSeriesClicked(series);
public void ProductsDisplay_ConvertToMp3Clicked(object _, LibraryBook[] libraryBook) => ViewModel.ConvertToMp3Clicked(libraryBook);

View File

@@ -31,7 +31,7 @@ namespace LibationAvalonia.Views
if (Design.IsDesignMode)
{
ViewModels.MainVM.Configure_NonUI();
DataContext = new ProcessBookViewModel(MockLibraryBook.CreateBook());
DataContext = new ProcessBookViewModel(MockLibraryBook.CreateBook(), LibationFileManager.Configuration.Instance);
return;
}
}

View File

@@ -38,42 +38,42 @@ namespace LibationAvalonia.Views
var trialBook = MockLibraryBook.CreateBook();
List<ProcessBookViewModel> testList = new()
{
new ProcessBookViewModel(trialBook)
new ProcessBookViewModel(trialBook, Configuration.Instance)
{
Result = ProcessBookResult.FailedAbort,
Status = ProcessBookStatus.Failed,
},
new ProcessBookViewModel(trialBook)
new ProcessBookViewModel(trialBook, Configuration.Instance)
{
Result = ProcessBookResult.FailedSkip,
Status = ProcessBookStatus.Failed,
},
new ProcessBookViewModel(trialBook)
new ProcessBookViewModel(trialBook, Configuration.Instance)
{
Result = ProcessBookResult.FailedRetry,
Status = ProcessBookStatus.Failed,
},
new ProcessBookViewModel(trialBook)
new ProcessBookViewModel(trialBook, Configuration.Instance)
{
Result = ProcessBookResult.ValidationFail,
Status = ProcessBookStatus.Failed,
},
new ProcessBookViewModel(trialBook)
new ProcessBookViewModel(trialBook, Configuration.Instance)
{
Result = ProcessBookResult.Cancelled,
Status = ProcessBookStatus.Cancelled,
},
new ProcessBookViewModel(trialBook)
new ProcessBookViewModel(trialBook, Configuration.Instance)
{
Result = ProcessBookResult.Success,
Status = ProcessBookStatus.Completed,
},
new ProcessBookViewModel(trialBook)
new ProcessBookViewModel(trialBook, Configuration.Instance)
{
Result = ProcessBookResult.None,
Status = ProcessBookStatus.Working,
},
new ProcessBookViewModel(trialBook)
new ProcessBookViewModel(trialBook, Configuration.Instance)
{
Result = ProcessBookResult.None,
Status = ProcessBookStatus.Queued,

View File

@@ -26,7 +26,7 @@ namespace LibationAvalonia.Views
{
public partial class ProductsDisplay : UserControl
{
public event EventHandler<LibraryBook[]>? LiberateClicked;
public event LiberateClickedHandler? LiberateClicked;
public event EventHandler<SeriesEntry>? LiberateSeriesClicked;
public event EventHandler<LibraryBook[]>? ConvertToMp3Clicked;
public event EventHandler<LibraryBook>? TagsButtonClicked;
@@ -298,10 +298,29 @@ namespace LibationAvalonia.Views
args.ContextMenuItems.Add(new MenuItem
{
Header = ctx.DownloadSelectedText,
Command = ReactiveCommand.Create(() => LiberateClicked?.Invoke(this, ctx.LibraryBookEntries.Select(e => e.LibraryBook).ToArray()))
Command = ReactiveCommand.Create(() => LiberateClicked?.Invoke(this, ctx.LibraryBookEntries.Select(e => e.LibraryBook).ToArray(), Configuration.Instance))
});
}
#endregion
#region Download split by chapters
if (entries.Length == 1 && entries[0] is LibraryBookEntry entry3_a)
{
args.ContextMenuItems.Add(new MenuItem()
{
Header = ctx.DownloadAsChapters,
IsEnabled = ctx.DownloadAsChaptersEnabled,
Command = ReactiveCommand.Create(() =>
{
var config = Configuration.Instance.CreateEphemeralCopy();
config.AllowLibationFixup = config.SplitFilesByChapter = true;
var books = ctx.LibraryBookEntries.Select(e => e.LibraryBook).Where(lb => lb.Book.UserDefinedItem.BookStatus is not LiberatedStatus.Error).ToList();
//No need to persist BookStatus changes. They only needs to last long for the files to start downloading
books.ForEach(b => b.Book.UserDefinedItem.BookStatus = LiberatedStatus.NotLiberated);
LiberateClicked?.Invoke(this, [entry3_a.LibraryBook], config);
})
});
}
#endregion
#region Convert to Mp3
@@ -329,7 +348,7 @@ namespace LibationAvalonia.Views
entry4.Book.UserDefinedItem.BookStatus = LiberatedStatus.NotLiberated;
if (entry4.Book.HasPdf)
entry4.Book.UserDefinedItem.SetPdfStatus(LiberatedStatus.NotLiberated);
LiberateClicked?.Invoke(this, [entry4.LibraryBook]);
LiberateClicked?.Invoke(this, [entry4.LibraryBook], Configuration.Instance);
})
});
}
@@ -512,7 +531,7 @@ namespace LibationAvalonia.Views
}
else if (button.DataContext is LibraryBookEntry lbEntry)
{
LiberateClicked?.Invoke(this, [lbEntry.LibraryBook]);
LiberateClicked?.Invoke(this, [lbEntry.LibraryBook], Configuration.Instance);
}
}

View File

@@ -18,10 +18,10 @@ namespace LibationCli
public IEnumerable<string>? Asins { get; set; }
protected static TProcessable CreateProcessable<TProcessable>(EventHandler<LibraryBook>? completedAction = null)
where TProcessable : Processable, new()
where TProcessable : Processable, IProcessable<TProcessable>
{
var progressBar = new ConsoleProgressBar(Console.Out);
var strProc = new TProcessable();
var strProc = TProcessable.Create(Configuration.Instance);
LibraryBook? currentLibraryBook = null;
strProc.Begin += (o, e) =>

View File

@@ -138,15 +138,35 @@ namespace LibationFileManager
protected override LongPath? GetFilePathCustom(string productId)
=> GetFilePathsCustom(productId).FirstOrDefault();
//GetFilePathsCustom gets called for every book during LibraryCommands.GetCounts().
//Cache the results for a short time to avoid excessive file system hits.
private DateTime lastDlInProgressEnumeration;
private static TimeSpan dlInProgressCacheTime = TimeSpan.FromSeconds(10);
private IEnumerable<LongPath>? dlInProgressFilesCache;
protected override List<LongPath> GetFilePathsCustom(string productId)
{
if (DownloadsInProgressDirectory is not LongPath dlFolder)
return [];
var regex = GetBookSearchRegex(productId);
return FileUtility
.SaferEnumerateFiles(dlFolder, "*.*", SearchOption.AllDirectories)
.Where(s => regex.IsMatch(s)).ToList();
if (DateTime.UtcNow - lastDlInProgressEnumeration > dlInProgressCacheTime)
{
dlInProgressFilesCache = null;
}
if (dlInProgressFilesCache is null)
{
dlInProgressFilesCache
= FileUtility
.SaferEnumerateFiles(dlFolder, "*.*", SearchOption.AllDirectories)
.ToArray();
lastDlInProgressEnumeration = DateTime.UtcNow;
}
return dlInProgressFilesCache.Where(s => regex.IsMatch(s)).ToList();
}
public bool Exists(string productId) => GetFilePath(productId) is not null;

View File

@@ -154,6 +154,9 @@ namespace LibationFileManager
set => SetString(value);
}
[Description("Libation's display color theme")]
public Theme ThemeVariant { get => GetNonString(defaultValue: Theme.System); set => SetNonString(value); }
[Description("Allow Libation to fix up audiobook metadata")]
public bool AllowLibationFixup { get => GetNonString(defaultValue: true); set => SetNonString(value); }
@@ -261,6 +264,14 @@ namespace LibationFileManager
Ignore = 3
}
[JsonConverter(typeof(StringEnumConverter))]
public enum Theme
{
System = 0,
Light = 1,
Dark = 2
}
[JsonConverter(typeof(StringEnumConverter))]
public enum DateTimeSource
{
@@ -319,6 +330,9 @@ namespace LibationFileManager
[Description("Import episodes? (eg: podcasts) When unchecked, episodes will not be imported into Libation.")]
public bool ImportEpisodes { get => GetNonString(defaultValue: true); set => SetNonString(value); }
[Description("Import Audible Plus books (books you do not own)? When unchecked, Audible Plus books will not be imported into Libation.")]
public bool ImportPlusTitles { get => GetNonString(defaultValue: true); set => SetNonString(value); }
[Description("Download episodes? (eg: podcasts). When unchecked, episodes already in Libation will not be downloaded.")]
public bool DownloadEpisodes { get => GetNonString(defaultValue: true); set => SetNonString(value); }

View File

@@ -32,7 +32,14 @@ namespace LibationFileManager
}
private static readonly Configuration s_SingletonInstance = new();
public static Configuration Instance { get; private set; } = s_SingletonInstance;
public bool IsEphemeralInstance => JsonBackedDictionary is EphemeralDictionary;
public Configuration CreateEphemeralCopy()
{
var copy = new Configuration();
copy.LoadEphemeralSettings(Settings.GetJObject());
return copy;
}
private Configuration() { }
#endregion

View File

@@ -17,6 +17,7 @@ internal class EphemeralDictionary : IJsonBackedDictionary
JsonObject = dataStore;
}
public JObject GetJObject() => (JObject)JsonObject.DeepClone();
public bool Exists(string propertyName)
=> JsonObject.ContainsKey(propertyName);
public string? GetString(string propertyName, string? defaultValue = null)

View File

@@ -9,6 +9,7 @@ using System.Threading.Tasks;
namespace LibationUiBase.GridView;
public delegate void LiberateClickedHandler(object sender, System.Collections.Generic.IList<LibraryBook> libraryBooks, Configuration config);
public class GridContextMenu
{
public string CopyCellText => $"{Accelerator}Copy Cell Contents";
@@ -20,6 +21,7 @@ public class GridContextMenu
public string LocateFileDialogTitle => $"Locate the audio file for '{GridEntries[0].Book.TitleWithSubtitle}'";
public string LocateFileErrorMessage => "Error saving book's location";
public string ConvertToMp3Text => $"{Accelerator}Convert to Mp3";
public string DownloadAsChapters => $"Download {Accelerator}split by chapters";
public string ReDownloadText => "Re-download this audiobook";
public string DownloadSelectedText => "Download selected audiobooks";
public string EditTemplatesText => "Edit Templates";
@@ -33,6 +35,7 @@ public class GridContextMenu
public bool SetDownloadedEnabled => LibraryBookEntries.Any(ge => ge.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated || ge.Liberate.IsSeries);
public bool SetNotDownloadedEnabled => LibraryBookEntries.Any(ge => ge.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated || ge.Liberate.IsSeries);
public bool ConvertToMp3Enabled => LibraryBookEntries.Any(ge => ge.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated);
public bool DownloadAsChaptersEnabled => LibraryBookEntries.Any(ge => ge.Book.UserDefinedItem.BookStatus is not LiberatedStatus.Error);
public bool ReDownloadEnabled => LibraryBookEntries.Any(ge => ge.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated);
private GridEntry[] GridEntries { get; }

View File

@@ -43,6 +43,7 @@ public enum ProcessBookStatus
public class ProcessBookViewModel : ReactiveObject
{
public LibraryBook LibraryBook { get; protected set; }
public Configuration Configuration { get; }
#region Properties exposed to the view
public ProcessBookResult Result { get => field; set { RaiseAndSetIfChanged(ref field, value); RaisePropertyChanged(nameof(StatusText)); } }
@@ -95,9 +96,10 @@ public class ProcessBookViewModel : ReactiveObject
/// <summary> A series of Processable actions to perform on this book </summary>
protected Queue<Func<Processable>> Processes { get; } = new();
public ProcessBookViewModel(LibraryBook libraryBook)
public ProcessBookViewModel(LibraryBook libraryBook, Configuration configuration)
{
LibraryBook = libraryBook;
Configuration = configuration;
Title = LibraryBook.Book.TitleWithSubtitle;
Author = LibraryBook.Book.AuthorNames;
@@ -203,9 +205,9 @@ public class ProcessBookViewModel : ReactiveObject
public ProcessBookViewModel AddDownloadDecryptBook() => AddProcessable<DownloadDecryptBook>();
public ProcessBookViewModel AddConvertToMp3() => AddProcessable<ConvertToMp3>();
private ProcessBookViewModel AddProcessable<T>() where T : Processable, new()
private ProcessBookViewModel AddProcessable<T>() where T : Processable, IProcessable<T>
{
Processes.Enqueue(() => new T());
Processes.Enqueue(() => T.Create(Configuration));
return this;
}
@@ -260,7 +262,7 @@ public class ProcessBookViewModel : ReactiveObject
private byte[] AudioDecodable_RequestCoverArt(object? sender, EventArgs e)
{
var quality
= Configuration.Instance.FileDownloadQuality == Configuration.DownloadQuality.High && LibraryBook.Book.PictureLarge is not null
= Configuration.FileDownloadQuality == Configuration.DownloadQuality.High && LibraryBook.Book.PictureLarge is not null
? new PictureDefinition(LibraryBook.Book.PictureLarge, PictureSize.Native)
: new PictureDefinition(LibraryBook.Book.PictureId, PictureSize._500x500);
@@ -345,7 +347,7 @@ public class ProcessBookViewModel : ReactiveObject
const DialogResult SkipResult = DialogResult.Ignore;
LogError($"ERROR. All books have not been processed. Book failed: {libraryBook.Book}");
DialogResult? dialogResult = Configuration.Instance.BadBook switch
DialogResult? dialogResult = Configuration.BadBook switch
{
Configuration.BadBookAction.Abort => DialogResult.Abort,
Configuration.BadBookAction.Retry => DialogResult.Retry,

View File

@@ -27,7 +27,7 @@ public class ProcessQueueViewModel : ReactiveObject
{
Queue.QueuedCountChanged += Queue_QueuedCountChanged;
Queue.CompletedCountChanged += Queue_CompletedCountChanged;
SpeedLimit = LibationFileManager.Configuration.Instance.DownloadSpeedLimit / 1024m / 1024;
SpeedLimit = Configuration.Instance.DownloadSpeedLimit / 1024m / 1024;
}
public int CompletedCount { get => field; private set { RaiseAndSetIfChanged(ref field, value); RaisePropertyChanged(nameof(AnyCompleted)); } }
@@ -48,7 +48,7 @@ public class ProcessQueueViewModel : ReactiveObject
set
{
var newValue = Math.Min(999 * 1024 * 1024, (long)Math.Ceiling(value * 1024 * 1024));
var config = LibationFileManager.Configuration.Instance;
var config = Configuration.Instance;
config.DownloadSpeedLimit = newValue;
_speedLimit
@@ -57,6 +57,8 @@ public class ProcessQueueViewModel : ReactiveObject
: 0;
config.DownloadSpeedLimit = (long)(_speedLimit * 1024 * 1024);
if (Queue.Current is ProcessBookViewModel currentBook)
currentBook.Configuration.DownloadSpeedLimit = config.DownloadSpeedLimit;
SpeedLimitIncrement = _speedLimit > 100 ? 10
: _speedLimit > 10 ? 1
@@ -89,24 +91,26 @@ public class ProcessQueueViewModel : ReactiveObject
#region Add Books to Queue
public bool QueueDownloadPdf(IList<LibraryBook> libraryBooks)
public bool QueueDownloadPdf(IList<LibraryBook> libraryBooks, Configuration? config = null)
{
if (!IsBooksDirectoryValid())
config ??= Configuration.Instance;
if (!IsBooksDirectoryValid(config))
return false;
var needsPdf = libraryBooks.Where(lb => lb.NeedsPdfDownload()).ToArray();
if (needsPdf.Length > 0)
{
Serilog.Log.Logger.Information("Begin download {count} pdfs", needsPdf.Length);
AddDownloadPdf(needsPdf);
AddDownloadPdf(needsPdf, config);
return true;
}
return false;
}
public bool QueueConvertToMp3(IList<LibraryBook> libraryBooks)
public bool QueueConvertToMp3(IList<LibraryBook> libraryBooks, Configuration? config = null)
{
if (!IsBooksDirectoryValid())
config ??= Configuration.Instance;
if (!IsBooksDirectoryValid(config))
return false;
//Only Queue Liberated books for conversion. This isn't a perfect filter, but it's better than nothing.
@@ -116,15 +120,16 @@ public class ProcessQueueViewModel : ReactiveObject
if (preLiberated.Length == 1)
RemoveCompleted(preLiberated[0]);
Serilog.Log.Logger.Information("Begin convert {count} books to mp3", preLiberated.Length);
AddConvertMp3(preLiberated);
AddConvertMp3(preLiberated, config);
return true;
}
return false;
}
public bool QueueDownloadDecrypt(IList<LibraryBook> libraryBooks)
public bool QueueDownloadDecrypt(IList<LibraryBook> libraryBooks, Configuration? config = null)
{
if (!IsBooksDirectoryValid())
config ??= Configuration.Instance;
if (!IsBooksDirectoryValid(config))
return false;
if (libraryBooks.Count == 1)
@@ -137,14 +142,14 @@ public class ProcessQueueViewModel : ReactiveObject
{
RemoveCompleted(item);
Serilog.Log.Logger.Information("Begin single library book backup of {libraryBook}", item);
AddDownloadDecrypt([item]);
AddDownloadDecrypt([item], config);
return true;
}
else if (item.NeedsPdfDownload())
{
RemoveCompleted(item);
Serilog.Log.Logger.Information("Begin single pdf backup of {libraryBook}", item);
AddDownloadPdf([item]);
AddDownloadPdf([item], config);
return true;
}
}
@@ -155,16 +160,16 @@ public class ProcessQueueViewModel : ReactiveObject
if (toLiberate.Length > 0)
{
Serilog.Log.Logger.Information("Begin backup of {count} library books", toLiberate.Length);
AddDownloadDecrypt(toLiberate);
AddDownloadDecrypt(toLiberate, config);
return true;
}
}
return false;
}
private bool IsBooksDirectoryValid()
private bool IsBooksDirectoryValid(Configuration config)
{
if (string.IsNullOrWhiteSpace(Configuration.Instance.Books))
if (string.IsNullOrWhiteSpace(config.Books))
{
Serilog.Log.Logger.Error("Books location is not set in configuration.");
MessageBoxBase.Show(
@@ -176,9 +181,9 @@ public class ProcessQueueViewModel : ReactiveObject
}
else if (AudibleFileStorage.BooksDirectory is null)
{
Serilog.Log.Logger.Error("Failed to create books directory: {@booksDir}", Configuration.Instance.Books);
Serilog.Log.Logger.Error("Failed to create books directory: {@booksDir}", config.Books);
MessageBoxBase.Show(
$"Libation was unable to create the \"Books location\" folder at:\n{Configuration.Instance.Books}\n\nPlease change the Books location in the settings menu.",
$"Libation was unable to create the \"Books location\" folder at:\n{config.Books}\n\nPlease change the Books location in the settings menu.",
"Failed to Create Books Directory",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
@@ -186,9 +191,9 @@ public class ProcessQueueViewModel : ReactiveObject
}
else if (AudibleFileStorage.DownloadsInProgressDirectory is null)
{
Serilog.Log.Logger.Error("Failed to create DownloadsInProgressDirectory in {@InProgress}", Configuration.Instance.InProgress);
Serilog.Log.Logger.Error("Failed to create DownloadsInProgressDirectory in {@InProgress}", config.InProgress);
MessageBoxBase.Show(
$"Libation was unable to create the \"Downloads In Progress\" folder in:\n{Configuration.Instance.InProgress}\n\nPlease change the In Progress location in the settings menu.",
$"Libation was unable to create the \"Downloads In Progress\" folder in:\n{config.InProgress}\n\nPlease change the In Progress location in the settings menu.",
"Failed to Create Downloads In Progress Directory",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
@@ -196,9 +201,9 @@ public class ProcessQueueViewModel : ReactiveObject
}
else if (AudibleFileStorage.DecryptInProgressDirectory is null)
{
Serilog.Log.Logger.Error("Failed to create DecryptInProgressDirectory in {@InProgress}", Configuration.Instance.InProgress);
Serilog.Log.Logger.Error("Failed to create DecryptInProgressDirectory in {@InProgress}", config.InProgress);
MessageBoxBase.Show(
$"Libation was unable to create the \"Decrypt In Progress\" folder in:\n{Configuration.Instance.InProgress}\n\nPlease change the In Progress location in the settings menu.",
$"Libation was unable to create the \"Decrypt In Progress\" folder in:\n{config.InProgress}\n\nPlease change the In Progress location in the settings menu.",
"Failed to Create Decrypt In Progress Directory",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
@@ -218,34 +223,34 @@ public class ProcessQueueViewModel : ReactiveObject
&& entry.Status is ProcessBookStatus.Completed
&& Queue.RemoveCompleted(entry);
private void AddDownloadPdf(IList<LibraryBook> entries)
private void AddDownloadPdf(IList<LibraryBook> entries, Configuration config)
{
var procs = entries.Where(e => !IsBookInQueue(e)).Select(Create).ToArray();
Serilog.Log.Logger.Information("Queueing {count} books for PDF-only download", procs.Length);
AddToQueue(procs);
ProcessBookViewModel Create(LibraryBook entry)
=> new ProcessBookViewModel(entry).AddDownloadPdf();
=> new ProcessBookViewModel(entry, config).AddDownloadPdf();
}
private void AddDownloadDecrypt(IList<LibraryBook> entries)
private void AddDownloadDecrypt(IList<LibraryBook> entries, Configuration config)
{
var procs = entries.Where(e => !IsBookInQueue(e)).Select(Create).ToArray();
Serilog.Log.Logger.Information("Queueing {count} books ofr download/decrypt", procs.Length);
AddToQueue(procs);
ProcessBookViewModel Create(LibraryBook entry)
=> new ProcessBookViewModel(entry).AddDownloadDecryptBook().AddDownloadPdf();
=> new ProcessBookViewModel(entry, config).AddDownloadDecryptBook().AddDownloadPdf();
}
private void AddConvertMp3(IList<LibraryBook> entries)
private void AddConvertMp3(IList<LibraryBook> entries, Configuration config)
{
var procs = entries.Where(e => !IsBookInQueue(e)).Select(Create).ToArray();
Serilog.Log.Logger.Information("Queueing {count} books for mp3 conversion", procs.Length);
AddToQueue(procs);
ProcessBookViewModel Create(LibraryBook entry)
=> new ProcessBookViewModel(entry).AddConvertToMp3();
=> new ProcessBookViewModel(entry, config).AddConvertToMp3();
}
private void AddToQueue(IList<ProcessBookViewModel> pbook)
@@ -282,7 +287,7 @@ public class ProcessQueueViewModel : ReactiveObject
}
Serilog.Log.Logger.Information("Begin processing queued item: '{item_LibraryBook}'", nextBook.LibraryBook);
SpeedLimit = nextBook.Configuration.DownloadSpeedLimit / 1024m / 1024;
var result = await nextBook.ProcessOneAsync();
Serilog.Log.Logger.Information("Completed processing queued item: '{item_LibraryBook}' with result: {result}", nextBook.LibraryBook, result);

View File

@@ -1,8 +1,9 @@
using System.Windows.Forms;
using LibationWinForms.GridView;
using System.Windows.Forms;
namespace LibationWinForms
{
public class AccessibleDataGridViewButtonCell : DataGridViewButtonCell
public class AccessibleDataGridViewButtonCell : DataGridViewButtonCell
{
protected string AccessibilityName { get; }
@@ -24,7 +25,8 @@ namespace LibationWinForms
public AccessibleDataGridViewButtonCell(string accessibilityName) : base()
{
AccessibilityName = accessibilityName;
}
FlatStyle = Application.IsDarkModeEnabled ? FlatStyle.Flat : FlatStyle.System;
}
protected class ButtonCellAccessibilityObject : DataGridViewButtonCellAccessibleObject
{

View File

@@ -0,0 +1,45 @@
using System.Windows.Forms;
namespace LibationWinForms
{
public class AccessibleDataGridViewComboBoxCell : DataGridViewComboBoxCell
{
protected string AccessibilityName { get; }
/// <summary>
/// Get or set description for accessibility. eg: screen readers. Also sets the ToolTipText
/// </summary>
protected string AccessibilityDescription
{
get => field;
set
{
field = value;
ToolTipText = value;
}
}
protected override AccessibleObject CreateAccessibilityInstance() => new ComboBoxCellAccessibilityObject(this, name: AccessibilityName, description: AccessibilityDescription);
public AccessibleDataGridViewComboBoxCell(string accessibilityName) : base()
{
FlatStyle = Application.IsDarkModeEnabled ? FlatStyle.Flat : FlatStyle.Standard;
AccessibilityName = accessibilityName;
}
protected class ComboBoxCellAccessibilityObject : DataGridViewComboBoxCellAccessibleObject
{
private string _name;
public override string Name => _name;
private string _description;
public override string Description => _description;
public ComboBoxCellAccessibilityObject(DataGridViewCell owner, string name, string description) : base(owner)
{
_name = name;
_description = description;
}
}
}
}

View File

@@ -18,6 +18,18 @@ namespace LibationWinForms
}
}
public int SelectionStart
{
get => textBox1.SelectionStart;
set => textBox1.SelectionStart = value;
}
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
textBox1.Focus();
}
public ClearableTextBox()
{
InitializeComponent();

View File

@@ -14,7 +14,7 @@ namespace LibationWinForms.Dialogs
InitializeComponent();
this.SetLibationIcon();
releaseNotesLbl.Text = $"Libation {AppScaffolding.LibationScaffolding.Variety} v{AppScaffolding.LibationScaffolding.BuildVersion}";
pictureBox1.Image = Application.IsDarkModeEnabled ? Properties.Resources.cheers_dark : Properties.Resources.cheers;
rmcrackanLbl.Tag = LibationContributor.PrimaryContributors.Single(c => c.Name == rmcrackanLbl.Text);
MBucariLbl.Tag = LibationContributor.PrimaryContributors.Single(c => c.Name == MBucariLbl.Text);
@@ -22,8 +22,13 @@ namespace LibationWinForms.Dialogs
{
var label = new LinkLabel { Tag = contributor, Text = contributor.Name, AutoSize = true };
label.LinkClicked += ContributorLabel_LinkClicked;
label.SetLinkLabelColors();
flowLayoutPanel1.Controls.Add(label);
}
rmcrackanLbl.SetLinkLabelColors();
MBucariLbl.SetLinkLabelColors();
releaseNotesLbl.SetLinkLabelColors();
getLibationLbl.SetLinkLabelColors();
var toolTip = new ToolTip();
toolTip.SetToolTip(releaseNotesLbl, "View Release Notes");

View File

@@ -31,11 +31,11 @@
this.cancelBtn = new System.Windows.Forms.Button();
this.saveBtn = new System.Windows.Forms.Button();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.DeleteAccount = new System.Windows.Forms.DataGridViewButtonColumn();
this.ExportAccount = new System.Windows.Forms.DataGridViewButtonColumn();
this.DeleteAccount = new DeleteColumn();
this.ExportAccount = new ExportColumn();
this.LibraryScan = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.AccountId = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Locale = new System.Windows.Forms.DataGridViewComboBoxColumn();
this.Locale = new LocaleColumn();
this.AccountName = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.importBtn = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
@@ -165,11 +165,11 @@
private System.Windows.Forms.Button saveBtn;
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.Button importBtn;
private System.Windows.Forms.DataGridViewButtonColumn DeleteAccount;
private System.Windows.Forms.DataGridViewButtonColumn ExportAccount;
private DeleteColumn DeleteAccount;
private ExportColumn ExportAccount;
private System.Windows.Forms.DataGridViewCheckBoxColumn LibraryScan;
private System.Windows.Forms.DataGridViewTextBoxColumn AccountId;
private System.Windows.Forms.DataGridViewComboBoxColumn Locale;
private LocaleColumn Locale;
private System.Windows.Forms.DataGridViewTextBoxColumn AccountName;
}
}

View File

@@ -20,7 +20,7 @@ namespace LibationWinForms.Dialogs
public AccountsDialog()
{
InitializeComponent();
dataGridView1.EnableHeadersVisualStyles = !Application.IsDarkModeEnabled;
dataGridView1.Columns[COL_AccountName].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
populateDropDown();
@@ -299,5 +299,55 @@ namespace LibationWinForms.Dialogs
ex);
}
}
#region Accessable Columns
public class DeleteColumn : DataGridViewButtonColumn
{
public DeleteColumn() : base()
{
this.CellTemplate = new DeleteColumnCell();
}
}
public class ExportColumn : DataGridViewButtonColumn
{
public ExportColumn() : base()
{
this.CellTemplate = new ExportColumnCell();
}
}
public class LocaleColumn : DataGridViewComboBoxColumn
{
public LocaleColumn() : base()
{
this.CellTemplate = new LocaleColumnCell();
}
}
public class DeleteColumnCell : AccessibleDataGridViewButtonCell
{
public DeleteColumnCell() : base("Delete account from Libation")
{
ToolTipText = AccessibilityName;
}
}
public class LocaleColumnCell : AccessibleDataGridViewComboBoxCell
{
public LocaleColumnCell() : base("Select Audible account region")
{
ToolTipText = AccessibilityName;
}
}
public class ExportColumnCell : AccessibleDataGridViewButtonCell
{
public ExportColumnCell() : base("Export account to mkb79/audible-cli format")
{
ToolTipText = AccessibilityName;
}
}
#endregion
}
}

View File

@@ -20,26 +20,34 @@ namespace LibationWinForms.Dialogs
public LiberatedStatus BookLiberatedStatus { get; private set; }
public LiberatedStatus? PdfLiberatedStatus { get; private set; }
private LibraryBook _libraryBook { get; }
private Book Book => _libraryBook.Book;
private Book Book => LibraryBook.Book;
public BookDetailsDialog()
{
InitializeComponent();
this.SetLibationIcon();
audibleLink.SetLinkLabelColors();
}
public BookDetailsDialog(LibraryBook libraryBook) : this()
public LibraryBook LibraryBook
{
_libraryBook = ArgumentValidator.EnsureNotNull(libraryBook, nameof(libraryBook));
initDetails();
initTags();
initLiberated();
get => field;
set
{
field = value;
initDetails();
initTags();
initLiberated();
}
}
// 1st draft: lazily cribbed from GridEntry.ctor()
private void initDetails()
{
audibleLink.LinkVisited = false;
this.Text = Book.TitleWithSubtitle;
dolbyAtmosPb.Visible = Book.IsSpatial;
dolbyAtmosPb.Image = Application.IsDarkModeEnabled ? Properties.Resources.Dolby_Atmos_Vertical_80_dark : Properties.Resources.Dolby_Atmos_Vertical_80;
(_, var picture) = PictureStorage.GetPicture(new PictureDefinition(Book.PictureId, PictureSize._80x80));
this.coverPb.Image = WinFormsUtil.TryLoadImageOrDefault(picture, PictureSize._80x80);
@@ -51,7 +59,7 @@ namespace LibationWinForms.Dialogs
Narrator(s): {Book.NarratorNames}
Length: {(Book.LengthInMinutes == 0 ? "" : $"{Book.LengthInMinutes / 60} hr {Book.LengthInMinutes % 60} min")}
Category: {string.Join(", ", Book.LowestCategoryNames())}
Purchase Date: {_libraryBook.DateAdded:d}
Purchase Date: {LibraryBook.DateAdded:d}
Language: {Book.Language}
Audible ID: {Book.AudibleProductId}
""";
@@ -135,9 +143,10 @@ namespace LibationWinForms.Dialogs
private void audibleLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
var locale = AudibleApi.Localization.Get(_libraryBook.Book.Locale);
var locale = AudibleApi.Localization.Get(Book.Locale);
var link = $"https://www.audible.{locale.TopDomain}/pd/{Book.AudibleProductId}";
Go.To.Url(link);
e.Link.Visited = true;
}
}
}

View File

@@ -21,7 +21,7 @@ namespace LibationWinForms.Dialogs
public BookRecordsDialog()
{
InitializeComponent();
dataGridView1.EnableHeadersVisualStyles = !Application.IsDarkModeEnabled;
if (!DesignMode)
{
//Prevent the designer from auto-generating columns

View File

@@ -55,7 +55,7 @@ namespace LibationWinForms.Dialogs
public EditQuickFilters()
{
InitializeComponent();
dataGridView1.EnableHeadersVisualStyles = !Application.IsDarkModeEnabled;
dataGridView1.Columns[COL_Filter].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
populateGridValues();

View File

@@ -149,6 +149,7 @@ namespace LibationWinForms.Dialogs
templateTb.Text = text.Insert(selStart, itemText);
templateTb.SelectionStart = selStart + itemText.Length;
templateTb.Focus();
}
private void llblGoToWiki_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)

View File

@@ -84,7 +84,7 @@
label3.Location = new System.Drawing.Point(4, 18);
label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
label3.Name = "label3";
label3.Size = new System.Drawing.Size(218, 120);
label3.Size = new System.Drawing.Size(218, 150);
label3.TabIndex = 2;
label3.Text = resources.GetString("label3.Text");
//
@@ -155,6 +155,7 @@
lboxIdFields.Name = "lboxIdFields";
lboxIdFields.Size = new System.Drawing.Size(220, 305);
lboxIdFields.TabIndex = 0;
lboxIdFields.DoubleClick += lboxFields_DoubleClick;
//
// label9
//
@@ -194,6 +195,7 @@
lboxBoolFields.Name = "lboxBoolFields";
lboxBoolFields.Size = new System.Drawing.Size(220, 365);
lboxBoolFields.TabIndex = 0;
lboxBoolFields.DoubleClick += lboxFields_DoubleClick;
//
// label8
//
@@ -229,10 +231,11 @@
//
lboxNumberFields.Dock = System.Windows.Forms.DockStyle.Fill;
lboxNumberFields.FormattingEnabled = true;
lboxNumberFields.Location = new System.Drawing.Point(3, 141);
lboxNumberFields.Location = new System.Drawing.Point(3, 171);
lboxNumberFields.Name = "lboxNumberFields";
lboxNumberFields.Size = new System.Drawing.Size(220, 275);
lboxNumberFields.Size = new System.Drawing.Size(220, 245);
lboxNumberFields.TabIndex = 0;
lboxNumberFields.DoubleClick += lboxFields_DoubleClick;
//
// label7
//
@@ -272,6 +275,7 @@
lboxStringFields.Name = "lboxStringFields";
lboxStringFields.Size = new System.Drawing.Size(220, 350);
lboxStringFields.TabIndex = 0;
lboxStringFields.DoubleClick += lboxFields_DoubleClick;
//
// label6
//

View File

@@ -1,5 +1,5 @@
using LibationSearchEngine;
using System.ComponentModel;
using System;
using System.Linq;
using System.Windows.Forms;
@@ -7,6 +7,7 @@ namespace LibationWinForms.Dialogs
{
public partial class SearchSyntaxDialog : Form
{
public event EventHandler<string> TagDoubleClicked;
public SearchSyntaxDialog()
{
InitializeComponent();
@@ -23,5 +24,13 @@ namespace LibationWinForms.Dialogs
base.OnFormClosing(e);
this.SaveSizeAndLocation(LibationFileManager.Configuration.Instance);
}
private void lboxFields_DoubleClick(object sender, EventArgs e)
{
if (sender is ListBox { SelectedItem: string tagName })
{
TagDoubleClicked?.Invoke(this, tagName);
}
}
}
}

View File

@@ -44,13 +44,14 @@
allowLibationFixupCbox = new System.Windows.Forms.CheckBox();
convertLossyRb = new System.Windows.Forms.RadioButton();
convertLosslessRb = new System.Windows.Forms.RadioButton();
inProgressSelectControl = new DirectorySelectControl();
logsBtn = new System.Windows.Forms.Button();
booksSelectControl = new DirectoryOrCustomSelectControl();
loggingLevelLbl = new System.Windows.Forms.Label();
loggingLevelCb = new System.Windows.Forms.ComboBox();
tabControl = new System.Windows.Forms.TabControl();
tab1ImportantSettings = new System.Windows.Forms.TabPage();
themeLbl = new System.Windows.Forms.Label();
themeCb = new System.Windows.Forms.ComboBox();
label22 = new System.Windows.Forms.Label();
groupBox1 = new System.Windows.Forms.GroupBox();
applyDisplaySettingsBtn = new System.Windows.Forms.Button();
gridScaleFactorLbl = new System.Windows.Forms.Label();
@@ -58,6 +59,7 @@
gridFontScaleFactorLbl = new System.Windows.Forms.Label();
gridFontScaleFactorTbar = new System.Windows.Forms.TrackBar();
booksGb = new System.Windows.Forms.GroupBox();
booksSelectControl = new DirectoryOrCustomSelectControl();
lastWriteTimeCb = new System.Windows.Forms.ComboBox();
creationTimeCb = new System.Windows.Forms.ComboBox();
lastWriteTimeLbl = new System.Windows.Forms.Label();
@@ -65,6 +67,7 @@
overwriteExistingCbox = new System.Windows.Forms.CheckBox();
saveEpisodesToSeriesFolderCbox = new System.Windows.Forms.CheckBox();
tab2ImportLibrary = new System.Windows.Forms.TabPage();
importPlusTitlesCb = new System.Windows.Forms.CheckBox();
autoDownloadEpisodesCb = new System.Windows.Forms.CheckBox();
autoScanCb = new System.Windows.Forms.CheckBox();
showImportedStatsCb = new System.Windows.Forms.CheckBox();
@@ -72,6 +75,7 @@
saveMetadataToFileCbox = new System.Windows.Forms.CheckBox();
useCoverAsFolderIconCb = new System.Windows.Forms.CheckBox();
inProgressFilesGb = new System.Windows.Forms.GroupBox();
inProgressSelectControl = new DirectoryOrCustomSelectControl();
customFileNamingGb = new System.Windows.Forms.GroupBox();
editCharreplacementBtn = new System.Windows.Forms.Button();
chapterFileTemplateBtn = new System.Windows.Forms.Button();
@@ -172,7 +176,7 @@
// inProgressDescLbl
//
inProgressDescLbl.AutoSize = true;
inProgressDescLbl.Location = new System.Drawing.Point(7, 19);
inProgressDescLbl.Location = new System.Drawing.Point(7, 17);
inProgressDescLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
inProgressDescLbl.Name = "inProgressDescLbl";
inProgressDescLbl.Size = new System.Drawing.Size(100, 45);
@@ -182,8 +186,8 @@
// saveBtn
//
saveBtn.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
saveBtn.Location = new System.Drawing.Point(668, 499);
saveBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
saveBtn.Location = new System.Drawing.Point(668, 501);
saveBtn.Margin = new System.Windows.Forms.Padding(4, 1, 4, 1);
saveBtn.Name = "saveBtn";
saveBtn.Size = new System.Drawing.Size(88, 27);
saveBtn.TabIndex = 98;
@@ -195,8 +199,8 @@
//
cancelBtn.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
cancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
cancelBtn.Location = new System.Drawing.Point(786, 499);
cancelBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
cancelBtn.Location = new System.Drawing.Point(785, 501);
cancelBtn.Margin = new System.Windows.Forms.Padding(1);
cancelBtn.Name = "cancelBtn";
cancelBtn.Size = new System.Drawing.Size(88, 27);
cancelBtn.TabIndex = 99;
@@ -217,10 +221,10 @@
// downloadEpisodesCb
//
downloadEpisodesCb.AutoSize = true;
downloadEpisodesCb.Location = new System.Drawing.Point(6, 81);
downloadEpisodesCb.Location = new System.Drawing.Point(6, 106);
downloadEpisodesCb.Name = "downloadEpisodesCb";
downloadEpisodesCb.Size = new System.Drawing.Size(163, 19);
downloadEpisodesCb.TabIndex = 4;
downloadEpisodesCb.TabIndex = 5;
downloadEpisodesCb.Text = "[download episodes desc]";
downloadEpisodesCb.UseVisualStyleBackColor = true;
//
@@ -341,15 +345,6 @@
convertLosslessRb.UseVisualStyleBackColor = true;
convertLosslessRb.CheckedChanged += convertFormatRb_CheckedChanged;
//
// inProgressSelectControl
//
inProgressSelectControl.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
inProgressSelectControl.Location = new System.Drawing.Point(6, 85);
inProgressSelectControl.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
inProgressSelectControl.Name = "inProgressSelectControl";
inProgressSelectControl.Size = new System.Drawing.Size(830, 49);
inProgressSelectControl.TabIndex = 19;
//
// logsBtn
//
logsBtn.Location = new System.Drawing.Point(256, 424);
@@ -360,15 +355,6 @@
logsBtn.UseVisualStyleBackColor = true;
logsBtn.Click += logsBtn_Click;
//
// booksSelectControl
//
booksSelectControl.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
booksSelectControl.Location = new System.Drawing.Point(6, 37);
booksSelectControl.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
booksSelectControl.Name = "booksSelectControl";
booksSelectControl.Size = new System.Drawing.Size(832, 102);
booksSelectControl.TabIndex = 2;
//
// loggingLevelLbl
//
loggingLevelLbl.AutoSize = true;
@@ -397,12 +383,16 @@
tabControl.Location = new System.Drawing.Point(12, 12);
tabControl.Name = "tabControl";
tabControl.SelectedIndex = 0;
tabControl.Size = new System.Drawing.Size(864, 481);
tabControl.Size = new System.Drawing.Size(864, 485);
tabControl.TabIndex = 100;
//
// tab1ImportantSettings
//
tab1ImportantSettings.AutoScroll = true;
tab1ImportantSettings.BackColor = System.Drawing.SystemColors.Window;
tab1ImportantSettings.Controls.Add(themeLbl);
tab1ImportantSettings.Controls.Add(themeCb);
tab1ImportantSettings.Controls.Add(label22);
tab1ImportantSettings.Controls.Add(groupBox1);
tab1ImportantSettings.Controls.Add(booksGb);
tab1ImportantSettings.Controls.Add(logsBtn);
@@ -411,10 +401,37 @@
tab1ImportantSettings.Location = new System.Drawing.Point(4, 24);
tab1ImportantSettings.Name = "tab1ImportantSettings";
tab1ImportantSettings.Padding = new System.Windows.Forms.Padding(3);
tab1ImportantSettings.Size = new System.Drawing.Size(856, 453);
tab1ImportantSettings.Size = new System.Drawing.Size(856, 457);
tab1ImportantSettings.TabIndex = 0;
tab1ImportantSettings.Text = "Important settings";
tab1ImportantSettings.UseVisualStyleBackColor = true;
//
// themeLbl
//
themeLbl.AutoSize = true;
themeLbl.Location = new System.Drawing.Point(190, 393);
themeLbl.Name = "themeLbl";
themeLbl.Size = new System.Drawing.Size(296, 15);
themeLbl.TabIndex = 12;
themeLbl.Text = "You must restart Libation for this change to take effect.";
//
// themeCb
//
themeCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
themeCb.FormattingEnabled = true;
themeCb.Location = new System.Drawing.Point(63, 390);
themeCb.Name = "themeCb";
themeCb.Size = new System.Drawing.Size(121, 23);
themeCb.TabIndex = 11;
themeCb.SelectedIndexChanged += themeCb_SelectedIndexChanged;
//
// label22
//
label22.AutoSize = true;
label22.Location = new System.Drawing.Point(4, 393);
label22.Name = "label22";
label22.Size = new System.Drawing.Size(44, 15);
label22.TabIndex = 10;
label22.Text = "Theme";
//
// groupBox1
//
@@ -434,7 +451,7 @@
// applyDisplaySettingsBtn
//
applyDisplaySettingsBtn.Anchor = System.Windows.Forms.AnchorStyles.Right;
applyDisplaySettingsBtn.Location = new System.Drawing.Point(689, 26);
applyDisplaySettingsBtn.Location = new System.Drawing.Point(672, 26);
applyDisplaySettingsBtn.Name = "applyDisplaySettingsBtn";
applyDisplaySettingsBtn.Size = new System.Drawing.Size(148, 34);
applyDisplaySettingsBtn.TabIndex = 9;
@@ -487,13 +504,13 @@
// booksGb
//
booksGb.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
booksGb.Controls.Add(booksSelectControl);
booksGb.Controls.Add(lastWriteTimeCb);
booksGb.Controls.Add(creationTimeCb);
booksGb.Controls.Add(lastWriteTimeLbl);
booksGb.Controls.Add(creationTimeLbl);
booksGb.Controls.Add(overwriteExistingCbox);
booksGb.Controls.Add(saveEpisodesToSeriesFolderCbox);
booksGb.Controls.Add(booksSelectControl);
booksGb.Controls.Add(booksLocationDescLbl);
booksGb.Location = new System.Drawing.Point(6, 6);
booksGb.Name = "booksGb";
@@ -502,6 +519,14 @@
booksGb.TabStop = false;
booksGb.Text = "Books location";
//
// booksSelectControl
//
booksSelectControl.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
booksSelectControl.Location = new System.Drawing.Point(8, 37);
booksSelectControl.Name = "booksSelectControl";
booksSelectControl.Size = new System.Drawing.Size(830, 80);
booksSelectControl.TabIndex = 6;
//
// lastWriteTimeCb
//
lastWriteTimeCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
@@ -563,6 +588,8 @@
// tab2ImportLibrary
//
tab2ImportLibrary.AutoScroll = true;
tab2ImportLibrary.BackColor = System.Drawing.SystemColors.Window;
tab2ImportLibrary.Controls.Add(importPlusTitlesCb);
tab2ImportLibrary.Controls.Add(autoDownloadEpisodesCb);
tab2ImportLibrary.Controls.Add(autoScanCb);
tab2ImportLibrary.Controls.Add(showImportedStatsCb);
@@ -571,18 +598,27 @@
tab2ImportLibrary.Location = new System.Drawing.Point(4, 24);
tab2ImportLibrary.Name = "tab2ImportLibrary";
tab2ImportLibrary.Padding = new System.Windows.Forms.Padding(3);
tab2ImportLibrary.Size = new System.Drawing.Size(856, 453);
tab2ImportLibrary.Size = new System.Drawing.Size(856, 457);
tab2ImportLibrary.TabIndex = 1;
tab2ImportLibrary.Text = "Import library";
tab2ImportLibrary.UseVisualStyleBackColor = true;
//
// importPlusTitlesCb
//
importPlusTitlesCb.AutoSize = true;
importPlusTitlesCb.Location = new System.Drawing.Point(6, 81);
importPlusTitlesCb.Name = "importPlusTitlesCb";
importPlusTitlesCb.Size = new System.Drawing.Size(199, 19);
importPlusTitlesCb.TabIndex = 4;
importPlusTitlesCb.Text = "[import audible plus books desc]";
importPlusTitlesCb.UseVisualStyleBackColor = true;
//
// autoDownloadEpisodesCb
//
autoDownloadEpisodesCb.AutoSize = true;
autoDownloadEpisodesCb.Location = new System.Drawing.Point(6, 106);
autoDownloadEpisodesCb.Location = new System.Drawing.Point(6, 131);
autoDownloadEpisodesCb.Name = "autoDownloadEpisodesCb";
autoDownloadEpisodesCb.Size = new System.Drawing.Size(190, 19);
autoDownloadEpisodesCb.TabIndex = 5;
autoDownloadEpisodesCb.TabIndex = 6;
autoDownloadEpisodesCb.Text = "[auto download episodes desc]";
autoDownloadEpisodesCb.UseVisualStyleBackColor = true;
//
@@ -609,6 +645,7 @@
// tab3DownloadDecrypt
//
tab3DownloadDecrypt.AutoScroll = true;
tab3DownloadDecrypt.BackColor = System.Drawing.SystemColors.Window;
tab3DownloadDecrypt.Controls.Add(saveMetadataToFileCbox);
tab3DownloadDecrypt.Controls.Add(useCoverAsFolderIconCb);
tab3DownloadDecrypt.Controls.Add(inProgressFilesGb);
@@ -617,15 +654,15 @@
tab3DownloadDecrypt.Location = new System.Drawing.Point(4, 24);
tab3DownloadDecrypt.Name = "tab3DownloadDecrypt";
tab3DownloadDecrypt.Padding = new System.Windows.Forms.Padding(3);
tab3DownloadDecrypt.Size = new System.Drawing.Size(856, 453);
tab3DownloadDecrypt.Size = new System.Drawing.Size(856, 457);
tab3DownloadDecrypt.TabIndex = 2;
tab3DownloadDecrypt.Text = "Download/Decrypt";
tab3DownloadDecrypt.UseVisualStyleBackColor = true;
//
// saveMetadataToFileCbox
//
saveMetadataToFileCbox.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
saveMetadataToFileCbox.AutoSize = true;
saveMetadataToFileCbox.Location = new System.Drawing.Point(482, 428);
saveMetadataToFileCbox.Location = new System.Drawing.Point(481, 435);
saveMetadataToFileCbox.Name = "saveMetadataToFileCbox";
saveMetadataToFileCbox.Size = new System.Drawing.Size(166, 19);
saveMetadataToFileCbox.TabIndex = 22;
@@ -634,8 +671,9 @@
//
// useCoverAsFolderIconCb
//
useCoverAsFolderIconCb.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
useCoverAsFolderIconCb.AutoSize = true;
useCoverAsFolderIconCb.Location = new System.Drawing.Point(7, 428);
useCoverAsFolderIconCb.Location = new System.Drawing.Point(6, 435);
useCoverAsFolderIconCb.Name = "useCoverAsFolderIconCb";
useCoverAsFolderIconCb.Size = new System.Drawing.Size(180, 19);
useCoverAsFolderIconCb.TabIndex = 22;
@@ -644,16 +682,24 @@
//
// inProgressFilesGb
//
inProgressFilesGb.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
inProgressFilesGb.Controls.Add(inProgressDescLbl);
inProgressFilesGb.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
inProgressFilesGb.Controls.Add(inProgressSelectControl);
inProgressFilesGb.Controls.Add(inProgressDescLbl);
inProgressFilesGb.Location = new System.Drawing.Point(6, 281);
inProgressFilesGb.Name = "inProgressFilesGb";
inProgressFilesGb.Size = new System.Drawing.Size(842, 141);
inProgressFilesGb.Size = new System.Drawing.Size(842, 148);
inProgressFilesGb.TabIndex = 21;
inProgressFilesGb.TabStop = false;
inProgressFilesGb.Text = "In progress files";
//
// inProgressSelectControl
//
inProgressSelectControl.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
inProgressSelectControl.Location = new System.Drawing.Point(6, 65);
inProgressSelectControl.Name = "inProgressSelectControl";
inProgressSelectControl.Size = new System.Drawing.Size(830, 80);
inProgressSelectControl.TabIndex = 19;
//
// customFileNamingGb
//
customFileNamingGb.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
@@ -775,6 +821,7 @@
// tab4AudioFileOptions
//
tab4AudioFileOptions.AutoScroll = true;
tab4AudioFileOptions.BackColor = System.Drawing.SystemColors.Window;
tab4AudioFileOptions.Controls.Add(request_xHE_AAC_Cbox);
tab4AudioFileOptions.Controls.Add(requestSpatialCbox);
tab4AudioFileOptions.Controls.Add(useWidevineCbox);
@@ -798,10 +845,9 @@
tab4AudioFileOptions.Location = new System.Drawing.Point(4, 24);
tab4AudioFileOptions.Name = "tab4AudioFileOptions";
tab4AudioFileOptions.Padding = new System.Windows.Forms.Padding(3);
tab4AudioFileOptions.Size = new System.Drawing.Size(856, 453);
tab4AudioFileOptions.Size = new System.Drawing.Size(856, 457);
tab4AudioFileOptions.TabIndex = 3;
tab4AudioFileOptions.Text = "Audio File Options";
tab4AudioFileOptions.UseVisualStyleBackColor = true;
//
// request_xHE_AAC_Cbox
//
@@ -1183,6 +1229,7 @@
//
label19.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
label19.AutoSize = true;
label19.BackColor = System.Drawing.SystemColors.ControlLightLight;
label19.Location = new System.Drawing.Point(332, 47);
label19.Name = "label19";
label19.Size = new System.Drawing.Size(20, 15);
@@ -1193,6 +1240,7 @@
//
label18.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
label18.AutoSize = true;
label18.BackColor = System.Drawing.SystemColors.ControlLightLight;
label18.Location = new System.Drawing.Point(291, 47);
label18.Name = "label18";
label18.Size = new System.Drawing.Size(20, 15);
@@ -1203,6 +1251,7 @@
//
label17.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
label17.AutoSize = true;
label17.BackColor = System.Drawing.SystemColors.ControlLightLight;
label17.Location = new System.Drawing.Point(251, 47);
label17.Name = "label17";
label17.Size = new System.Drawing.Size(20, 15);
@@ -1213,6 +1262,7 @@
//
label16.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
label16.AutoSize = true;
label16.BackColor = System.Drawing.SystemColors.ControlLightLight;
label16.Location = new System.Drawing.Point(212, 47);
label16.Name = "label16";
label16.Size = new System.Drawing.Size(20, 15);
@@ -1223,6 +1273,7 @@
//
label12.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
label12.AutoSize = true;
label12.BackColor = System.Drawing.SystemColors.ControlLightLight;
label12.Location = new System.Drawing.Point(170, 47);
label12.Name = "label12";
label12.Size = new System.Drawing.Size(20, 15);
@@ -1233,6 +1284,7 @@
//
label15.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
label15.AutoSize = true;
label15.BackColor = System.Drawing.SystemColors.ControlLightLight;
label15.Location = new System.Drawing.Point(130, 47);
label15.Name = "label15";
label15.Size = new System.Drawing.Size(20, 15);
@@ -1243,6 +1295,7 @@
//
label9.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
label9.AutoSize = true;
label9.BackColor = System.Drawing.SystemColors.ControlLightLight;
label9.Location = new System.Drawing.Point(89, 47);
label9.Name = "label9";
label9.Size = new System.Drawing.Size(20, 15);
@@ -1253,6 +1306,7 @@
//
label8.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
label8.AutoSize = true;
label8.BackColor = System.Drawing.SystemColors.ControlLightLight;
label8.Location = new System.Drawing.Point(371, 47);
label8.Name = "label8";
label8.Size = new System.Drawing.Size(20, 15);
@@ -1281,6 +1335,7 @@
//
label14.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
label14.AutoSize = true;
label14.BackColor = System.Drawing.SystemColors.ControlLightLight;
label14.Location = new System.Drawing.Point(50, 47);
label14.Name = "label14";
label14.Size = new System.Drawing.Size(20, 15);
@@ -1291,6 +1346,7 @@
//
label2.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
label2.AutoSize = true;
label2.BackColor = System.Drawing.SystemColors.ControlLightLight;
label2.Location = new System.Drawing.Point(10, 47);
label2.Name = "label2";
label2.Size = new System.Drawing.Size(20, 15);
@@ -1464,8 +1520,6 @@
public System.Windows.Forms.Button saveBtn;
public System.Windows.Forms.Button cancelBtn;
private System.Windows.Forms.CheckBox allowLibationFixupCbox;
private DirectoryOrCustomSelectControl booksSelectControl;
private DirectorySelectControl inProgressSelectControl;
private System.Windows.Forms.RadioButton convertLossyRb;
private System.Windows.Forms.RadioButton convertLosslessRb;
private System.Windows.Forms.Button logsBtn;
@@ -1568,5 +1622,11 @@
private System.Windows.Forms.CheckBox useWidevineCbox;
private System.Windows.Forms.CheckBox requestSpatialCbox;
private System.Windows.Forms.CheckBox request_xHE_AAC_Cbox;
private DirectoryOrCustomSelectControl inProgressSelectControl;
private DirectoryOrCustomSelectControl booksSelectControl;
private System.Windows.Forms.Label label22;
private System.Windows.Forms.ComboBox themeCb;
private System.Windows.Forms.Label themeLbl;
private System.Windows.Forms.CheckBox importPlusTitlesCb;
}
}

View File

@@ -12,12 +12,14 @@ namespace LibationWinForms.Dialogs
this.autoScanCb.Text = desc(nameof(config.AutoScan));
this.showImportedStatsCb.Text = desc(nameof(config.ShowImportedStats));
this.importEpisodesCb.Text = desc(nameof(config.ImportEpisodes));
this.importPlusTitlesCb.Text = desc(nameof(config.ImportPlusTitles));
this.downloadEpisodesCb.Text = desc(nameof(config.DownloadEpisodes));
this.autoDownloadEpisodesCb.Text = desc(nameof(config.AutoDownloadEpisodes));
autoScanCb.Checked = config.AutoScan;
showImportedStatsCb.Checked = config.ShowImportedStats;
importEpisodesCb.Checked = config.ImportEpisodes;
importPlusTitlesCb.Checked = config.ImportPlusTitles;
downloadEpisodesCb.Checked = config.DownloadEpisodes;
autoDownloadEpisodesCb.Checked = config.AutoDownloadEpisodes;
}
@@ -26,6 +28,7 @@ namespace LibationWinForms.Dialogs
config.AutoScan = autoScanCb.Checked;
config.ShowImportedStats = showImportedStatsCb.Checked;
config.ImportEpisodes = importEpisodesCb.Checked;
config.ImportPlusTitles = importPlusTitlesCb.Checked;
config.DownloadEpisodes = downloadEpisodesCb.Checked;
config.AutoDownloadEpisodes = autoDownloadEpisodesCb.Checked;
}

View File

@@ -1,4 +1,6 @@
using Dinah.Core;
using DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Office2013.Theme;
using FileManager;
using LibationFileManager;
using LibationUiBase;
@@ -19,6 +21,8 @@ namespace LibationWinForms.Dialogs
else
Go.To.Folder(Configuration.Instance.LibationFiles.Location.ShortPathName);
}
private Configuration.Theme themeVariant;
private Configuration.Theme initialThemeVariant;
private void Load_Important(Configuration config)
{
@@ -44,6 +48,10 @@ namespace LibationWinForms.Dialogs
creationTimeCb.SelectedItem = dateTimeSources.SingleOrDefault(v => v.Value == config.CreationTime) ?? dateTimeSources[0];
lastWriteTimeCb.SelectedItem = dateTimeSources.SingleOrDefault(v => v.Value == config.LastWriteTime) ?? dateTimeSources[0];
themeVariant = initialThemeVariant = config.ThemeVariant;
var themes = Enum.GetValues<Configuration.Theme>().Select(v => new EnumDisplay<Configuration.Theme>(v)).ToArray();
themeCb.Items.AddRange(themes);
themeCb.SelectedItem = themes.SingleOrDefault(v => v.Value == themeVariant) ?? themes[0];
booksSelectControl.SetSearchTitle("books location");
booksSelectControl.SetDirectoryItems(
@@ -110,6 +118,7 @@ namespace LibationWinForms.Dialogs
config.CreationTime = (creationTimeCb.SelectedItem as EnumDisplay<Configuration.DateTimeSource>)?.Value ?? Configuration.DateTimeSource.File;
config.LastWriteTime = (lastWriteTimeCb.SelectedItem as EnumDisplay<Configuration.DateTimeSource>)?.Value ?? Configuration.DateTimeSource.File;
config.ThemeVariant = (themeCb.SelectedItem as EnumDisplay<Configuration.Theme>)?.Value ?? Configuration.Theme.System;
return true;
}
@@ -123,5 +132,15 @@ namespace LibationWinForms.Dialogs
config.GridFontScaleFactor = linearRangeToScaleFactor(gridFontScaleFactorTbar.Value);
config.GridScaleFactor = linearRangeToScaleFactor(gridScaleFactorTbar.Value);
}
private void themeCb_SelectedIndexChanged(object? sender, EventArgs e)
{
var selected = themeCb.SelectedItem as EnumDisplay<Configuration.Theme>;
if (selected != null)
{
themeVariant = selected.Value;
themeLbl.Visible = themeVariant != initialThemeVariant;
}
}
}
}

View File

@@ -8,7 +8,7 @@ namespace LibationWinForms
{
protected void Configure_Filter() { }
private void filterHelpBtn_Click(object sender, EventArgs e) => new SearchSyntaxDialog().ShowDialog();
private void filterHelpBtn_Click(object sender, EventArgs e) => ShowSearchSyntaxDialog();
private void filterSearchTb_TextCleared(object sender, EventArgs e)
{
@@ -45,5 +45,32 @@ namespace LibationWinForms
performFilter(lastGoodFilter);
}
}
public SearchSyntaxDialog ShowSearchSyntaxDialog()
{
var dialog = new SearchSyntaxDialog();
dialog.TagDoubleClicked += Dialog_TagDoubleClicked;
dialog.FormClosed += Dialog_Closed;
filterHelpBtn.Enabled = false;
dialog.Show(this);
return dialog;
void Dialog_Closed(object sender, FormClosedEventArgs e)
{
dialog.TagDoubleClicked -= Dialog_TagDoubleClicked;
filterHelpBtn.Enabled = true;
}
void Dialog_TagDoubleClicked(object sender, string tag)
{
if (string.IsNullOrEmpty(tag)) return;
var text = filterSearchTb.Text;
var selStart = Math.Min(Math.Max(0, filterSearchTb.SelectionStart), text.Length);
filterSearchTb.Text = text.Insert(selStart, tag);
filterSearchTb.SelectionStart = selStart + tag.Length;
filterSearchTb.Focus();
}
}
}
}

View File

@@ -25,13 +25,13 @@ namespace LibationWinForms
this.Width = width;
}
private void ProductsDisplay_LiberateClicked(object sender, LibraryBook[] libraryBooks)
private void ProductsDisplay_LiberateClicked(object sender, System.Collections.Generic.IList<LibraryBook> libraryBooks, Configuration config)
{
try
{
if (processBookQueue1.ViewModel.QueueDownloadDecrypt(libraryBooks))
if (processBookQueue1.ViewModel.QueueDownloadDecrypt(libraryBooks, config))
SetQueueCollapseState(false);
else if (libraryBooks.Length == 1 && libraryBooks[0].Book.AudioExists)
else if (libraryBooks.Count == 1 && libraryBooks[0].Book.AudioExists)
{
// liberated: open explorer to file
var filePath = AudibleFileStorage.Audio.GetPath(libraryBooks[0].Book.AudibleProductId);

View File

@@ -21,6 +21,7 @@ namespace LibationWinForms
scanLibraryOfAllAccountsToolStripMenuItem.Enabled = false;
scanLibraryOfSomeAccountsToolStripMenuItem.Enabled = false;
this.scanningToolStripMenuItem.Image = System.Windows.Forms.Application.IsDarkModeEnabled ? Properties.Resources.import_16x16_dark : Properties.Resources.import_16x16;
this.scanningToolStripMenuItem.Visible = true;
this.scanningToolStripMenuItem.Text
= (accountsLength == 1)

View File

@@ -22,7 +22,7 @@ namespace LibationWinForms
PictureStorage.SetDefaultImage(PictureSize.Native, Properties.Resources.default_cover_500x500.ToBytes(format));
BaseUtil.SetLoadImageDelegate(WinFormsUtil.TryLoadImageOrDefault);
BaseUtil.SetLoadResourceImageDelegate(Properties.Resources.ResourceManager.GetObject);
BaseUtil.SetLoadResourceImageDelegate(LoadResourceImage);
// wire-up event to automatically download after scan.
// winforms only. this should NOT be allowed in cli
@@ -36,6 +36,13 @@ namespace LibationWinForms
};
}
private static object LoadResourceImage(string resourceName)
{
if (Application.IsDarkModeEnabled)
resourceName += "_dark";
return Properties.Resources.ResourceManager.GetObject(resourceName);
}
private void AudibleApiStorage_LoadError(object sender, AccountSettingsLoadErrorEventArgs e)
{
try

View File

@@ -23,7 +23,7 @@ namespace LibationWinForms.GridView
{
public EditTagsDataGridViewImageButtonCell() : base("Edit Tags button") { }
private static Image ButtonImage { get; } = Properties.Resources.edit_25x25;
private static Image ButtonImage => Application.IsDarkModeEnabled ? Properties.Resources.edit_25x25_dark : Properties.Resources.edit_25x25;
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{

View File

@@ -23,6 +23,8 @@ namespace LibationWinForms.GridView
private static readonly Brush DISABLED_GRAY = new SolidBrush(Color.FromArgb(0x60, Color.LightGray));
private static readonly Color HiddenForeColor = Color.LightGray;
private static readonly Color SERIES_BG_COLOR = Color.FromArgb(230, 255, 230);
private static readonly Color SERIES_BG_COLOR_DARK = Color.FromArgb(76, 82, 93);
private static Color SeriesBgColor => Application.IsDarkModeEnabled ? SERIES_BG_COLOR_DARK:SERIES_BG_COLOR;
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object? value, object? formattedValue, string? errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
@@ -32,7 +34,7 @@ namespace LibationWinForms.GridView
//Don't paint the button graphic
paintParts ^= DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.SelectionBackground;
row.DefaultCellStyle.BackColor = status.IsEpisode ? SERIES_BG_COLOR : grid.DefaultCellStyle.BackColor;
row.DefaultCellStyle.BackColor = status.IsEpisode ? SeriesBgColor : grid.DefaultCellStyle.BackColor;
row.DefaultCellStyle.ForeColor = status.Opacity == 1 ? grid.DefaultCellStyle.ForeColor : HiddenForeColor;
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts);

View File

@@ -14,6 +14,7 @@ using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LibationWinForms.GridView
{
public partial class ProductsDisplay : UserControl
@@ -21,7 +22,7 @@ namespace LibationWinForms.GridView
/// <summary>Number of visible rows has changed</summary>
public event EventHandler<int> VisibleCountChanged;
public event EventHandler<int> RemovableCountChanged;
public event EventHandler<LibraryBook[]> LiberateClicked;
public event LiberateClickedHandler LiberateClicked;
public event EventHandler<SeriesEntry> LiberateSeriesClicked;
public event EventHandler<LibraryBook[]> ConvertToMp3Clicked;
public event EventHandler InitialLoaded;
@@ -68,7 +69,7 @@ namespace LibationWinForms.GridView
PictureStorage.PictureCached -= PictureCached;
if (!imageDisplay.Visible)
imageDisplay.Show(null);
imageDisplay.Show(this);
}
private void productsGrid_DescriptionClicked(GridEntry liveGridEntry, Rectangle cellRectangle)
@@ -90,11 +91,27 @@ namespace LibationWinForms.GridView
displayWindow.Show(this);
}
private async void productsGrid_DetailsClicked(LibraryBookEntry liveGridEntry)
private BookDetailsDialog bookDetailsForm;
private void productsGrid_DetailsClicked(LibraryBookEntry liveGridEntry)
{
var bookDetailsForm = new BookDetailsDialog(liveGridEntry.LibraryBook);
if (bookDetailsForm.ShowDialog() == DialogResult.OK)
await liveGridEntry.LibraryBook.UpdateUserDefinedItemAsync(bookDetailsForm.NewTags, bookDetailsForm.BookLiberatedStatus, bookDetailsForm.PdfLiberatedStatus);
if (bookDetailsForm is null || bookDetailsForm.IsDisposed || !bookDetailsForm.Visible)
{
bookDetailsForm = new();
bookDetailsForm.RestoreSizeAndLocation(Configuration.Instance);
bookDetailsForm.FormClosed += bookDetailsForm_FormClosed;
}
bookDetailsForm.LibraryBook = liveGridEntry.LibraryBook;
if (!bookDetailsForm.Visible)
bookDetailsForm.Show(this);
async void bookDetailsForm_FormClosed(object sender, FormClosedEventArgs e)
{
bookDetailsForm.FormClosed -= bookDetailsForm_FormClosed;
bookDetailsForm.SaveSizeAndLocation(Configuration.Instance);
if (e.CloseReason is CloseReason.UserClosing && bookDetailsForm.DialogResult is DialogResult.OK)
await liveGridEntry.LibraryBook.UpdateUserDefinedItemAsync(bookDetailsForm.NewTags, bookDetailsForm.BookLiberatedStatus, bookDetailsForm.PdfLiberatedStatus);
}
}
#endregion
@@ -185,10 +202,31 @@ namespace LibationWinForms.GridView
ctxMenu.Items.Add(downloadSelectedMenuItem);
downloadSelectedMenuItem.Click += (s, _) =>
{
LiberateClicked?.Invoke(s, ctx.LibraryBookEntries.Select(e => e.LibraryBook).ToArray());
LiberateClicked?.Invoke(s, ctx.LibraryBookEntries.Select(e => e.LibraryBook).ToArray(), Configuration.Instance);
};
}
#endregion
#region Download split by chapters
if (ctx.LibraryBookEntries.Length > 0)
{
var downloadChaptersMenuItem = new ToolStripMenuItem
{
Text = ctx.DownloadAsChapters,
Enabled = ctx.DownloadAsChaptersEnabled
};
downloadChaptersMenuItem.Click += (_, e) =>
{
var config = Configuration.Instance.CreateEphemeralCopy();
config.AllowLibationFixup = config.SplitFilesByChapter = true;
var books = ctx.LibraryBookEntries.Select(e => e.LibraryBook).Where(lb => lb.Book.UserDefinedItem.BookStatus is not LiberatedStatus.Error).ToList();
books.ForEach(b => b.Book.UserDefinedItem.BookStatus = LiberatedStatus.NotLiberated);
LiberateClicked?.Invoke(this, books, config);
};
ctxMenu.Items.Add(downloadChaptersMenuItem);
}
#endregion
#region Convert to Mp3
@@ -201,7 +239,6 @@ namespace LibationWinForms.GridView
};
convertToMp3MenuItem.Click += (_, e) => ConvertToMp3Clicked?.Invoke(this, ctx.LibraryBookEntries.Select(e => e.LibraryBook).ToArray());
ctxMenu.Items.Add(convertToMp3MenuItem);
}
#endregion
@@ -222,7 +259,7 @@ namespace LibationWinForms.GridView
if (entry4.Book.HasPdf)
entry4.Book.UserDefinedItem.SetPdfStatus(LiberatedStatus.NotLiberated);
LiberateClicked?.Invoke(s, [entry4.LibraryBook]);
LiberateClicked?.Invoke(s, [entry4.LibraryBook], Configuration.Instance);
};
}
@@ -398,7 +435,7 @@ namespace LibationWinForms.GridView
{
if (liveGridEntry.LibraryBook.Book.UserDefinedItem.BookStatus is not LiberatedStatus.Error
&& !liveGridEntry.Liberate.IsUnavailable)
LiberateClicked?.Invoke(this, [liveGridEntry.LibraryBook]);
LiberateClicked?.Invoke(this, [liveGridEntry.LibraryBook], Configuration.Instance);
}
private void productsGrid_RemovableCountChanged(object sender, EventArgs e)

View File

@@ -53,6 +53,7 @@ namespace LibationWinForms.GridView
setGridScale(Configuration.Instance.GridScaleFactor);
Configuration.Instance.PropertyChanged += Configuration_ScaleChanged;
Configuration.Instance.PropertyChanged += Configuration_FontScaleChanged;
gridEntryDataGridView.EnableHeadersVisualStyles = !Application.IsDarkModeEnabled;
gridEntryDataGridView.Disposed += (_, _) =>
{

View File

@@ -29,184 +29,177 @@
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProcessBookControl));
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.remainingTimeLbl = new System.Windows.Forms.Label();
this.etaLbl = new System.Windows.Forms.Label();
this.cancelBtn = new System.Windows.Forms.Button();
this.statusLbl = new System.Windows.Forms.Label();
this.bookInfoLbl = new System.Windows.Forms.Label();
this.moveUpBtn = new System.Windows.Forms.Button();
this.moveDownBtn = new System.Windows.Forms.Button();
this.moveFirstBtn = new System.Windows.Forms.Button();
this.moveLastBtn = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
pictureBox1 = new System.Windows.Forms.PictureBox();
progressBar1 = new System.Windows.Forms.ProgressBar();
remainingTimeLbl = new System.Windows.Forms.Label();
etaLbl = new System.Windows.Forms.Label();
cancelBtn = new System.Windows.Forms.Button();
statusLbl = new System.Windows.Forms.Label();
bookInfoLbl = new System.Windows.Forms.Label();
moveUpBtn = new System.Windows.Forms.Button();
moveDownBtn = new System.Windows.Forms.Button();
moveFirstBtn = new System.Windows.Forms.Button();
moveLastBtn = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.Location = new System.Drawing.Point(2, 2);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(80, 80);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
pictureBox1.Location = new System.Drawing.Point(2, 2);
pictureBox1.Name = "pictureBox1";
pictureBox1.Size = new System.Drawing.Size(80, 80);
pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
pictureBox1.TabIndex = 0;
pictureBox1.TabStop = false;
//
// progressBar1
//
this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.progressBar1.Location = new System.Drawing.Point(88, 65);
this.progressBar1.MarqueeAnimationSpeed = 0;
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(212, 17);
this.progressBar1.TabIndex = 2;
progressBar1.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
progressBar1.Location = new System.Drawing.Point(88, 65);
progressBar1.MarqueeAnimationSpeed = 0;
progressBar1.Name = "progressBar1";
progressBar1.Size = new System.Drawing.Size(212, 17);
progressBar1.TabIndex = 2;
//
// remainingTimeLbl
//
this.remainingTimeLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.remainingTimeLbl.AutoSize = true;
this.remainingTimeLbl.Location = new System.Drawing.Point(338, 65);
this.remainingTimeLbl.Name = "remainingTimeLbl";
this.remainingTimeLbl.Size = new System.Drawing.Size(30, 15);
this.remainingTimeLbl.TabIndex = 3;
this.remainingTimeLbl.Text = "--:--";
this.remainingTimeLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
remainingTimeLbl.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
remainingTimeLbl.AutoSize = true;
remainingTimeLbl.Location = new System.Drawing.Point(338, 65);
remainingTimeLbl.Name = "remainingTimeLbl";
remainingTimeLbl.Size = new System.Drawing.Size(30, 15);
remainingTimeLbl.TabIndex = 3;
remainingTimeLbl.Text = "--:--";
remainingTimeLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// etaLbl
//
this.etaLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.etaLbl.AutoSize = true;
this.etaLbl.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.etaLbl.Location = new System.Drawing.Point(304, 66);
this.etaLbl.Name = "etaLbl";
this.etaLbl.Size = new System.Drawing.Size(28, 13);
this.etaLbl.TabIndex = 3;
this.etaLbl.Text = "ETA:";
this.etaLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
etaLbl.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
etaLbl.AutoSize = true;
etaLbl.Font = new System.Drawing.Font("Segoe UI", 8F);
etaLbl.Location = new System.Drawing.Point(304, 66);
etaLbl.Name = "etaLbl";
etaLbl.Size = new System.Drawing.Size(27, 13);
etaLbl.TabIndex = 3;
etaLbl.Text = "ETA:";
etaLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// cancelBtn
//
this.cancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cancelBtn.BackColor = System.Drawing.Color.Transparent;
this.cancelBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("cancelBtn.BackgroundImage")));
this.cancelBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.cancelBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.cancelBtn.ForeColor = System.Drawing.SystemColors.Control;
this.cancelBtn.Location = new System.Drawing.Point(348, 6);
this.cancelBtn.Margin = new System.Windows.Forms.Padding(0);
this.cancelBtn.Name = "cancelBtn";
this.cancelBtn.Size = new System.Drawing.Size(20, 20);
this.cancelBtn.TabIndex = 4;
this.cancelBtn.UseVisualStyleBackColor = false;
cancelBtn.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
cancelBtn.BackColor = System.Drawing.Color.Transparent;
cancelBtn.BackgroundImage = (System.Drawing.Image)resources.GetObject("cancelBtn.BackgroundImage");
cancelBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
cancelBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
cancelBtn.ForeColor = System.Drawing.SystemColors.Control;
cancelBtn.Location = new System.Drawing.Point(348, 6);
cancelBtn.Margin = new System.Windows.Forms.Padding(0);
cancelBtn.Name = "cancelBtn";
cancelBtn.Size = new System.Drawing.Size(20, 20);
cancelBtn.TabIndex = 4;
cancelBtn.UseVisualStyleBackColor = false;
//
// statusLbl
//
this.statusLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.statusLbl.AutoSize = true;
this.statusLbl.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.statusLbl.Location = new System.Drawing.Point(89, 66);
this.statusLbl.Name = "statusLbl";
this.statusLbl.Size = new System.Drawing.Size(50, 13);
this.statusLbl.TabIndex = 3;
this.statusLbl.Text = "[STATUS]";
this.statusLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
statusLbl.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
statusLbl.AutoSize = true;
statusLbl.Font = new System.Drawing.Font("Segoe UI", 8F);
statusLbl.Location = new System.Drawing.Point(89, 66);
statusLbl.Name = "statusLbl";
statusLbl.Size = new System.Drawing.Size(48, 13);
statusLbl.TabIndex = 3;
statusLbl.Text = "[STATUS]";
statusLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// bookInfoLbl
//
this.bookInfoLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.bookInfoLbl.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.bookInfoLbl.Location = new System.Drawing.Point(89, 6);
this.bookInfoLbl.Name = "bookInfoLbl";
this.bookInfoLbl.Size = new System.Drawing.Size(219, 56);
this.bookInfoLbl.TabIndex = 1;
this.bookInfoLbl.Text = "[multi-\r\nline\r\nbook\r\n info]";
bookInfoLbl.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
bookInfoLbl.Font = new System.Drawing.Font("Segoe UI", 8F);
bookInfoLbl.Location = new System.Drawing.Point(89, 6);
bookInfoLbl.Name = "bookInfoLbl";
bookInfoLbl.Size = new System.Drawing.Size(219, 56);
bookInfoLbl.TabIndex = 1;
bookInfoLbl.Text = "[multi-\r\nline\r\nbook\r\n info]";
//
// moveUpBtn
//
this.moveUpBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.moveUpBtn.BackColor = System.Drawing.Color.Transparent;
this.moveUpBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveUpBtn.BackgroundImage")));
this.moveUpBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.moveUpBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.moveUpBtn.ForeColor = System.Drawing.SystemColors.Control;
this.moveUpBtn.Location = new System.Drawing.Point(314, 24);
this.moveUpBtn.Name = "moveUpBtn";
this.moveUpBtn.Size = new System.Drawing.Size(30, 17);
this.moveUpBtn.TabIndex = 5;
this.moveUpBtn.UseVisualStyleBackColor = false;
moveUpBtn.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
moveUpBtn.BackColor = System.Drawing.Color.Transparent;
moveUpBtn.BackgroundImage = Properties.Resources.move_up;
moveUpBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
moveUpBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
moveUpBtn.ForeColor = System.Drawing.SystemColors.Control;
moveUpBtn.Location = new System.Drawing.Point(314, 24);
moveUpBtn.Name = "moveUpBtn";
moveUpBtn.Size = new System.Drawing.Size(30, 17);
moveUpBtn.TabIndex = 5;
moveUpBtn.UseVisualStyleBackColor = false;
//
// moveDownBtn
//
this.moveDownBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.moveDownBtn.BackColor = System.Drawing.Color.Transparent;
this.moveDownBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveDownBtn.BackgroundImage")));
this.moveDownBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.moveDownBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.moveDownBtn.ForeColor = System.Drawing.SystemColors.Control;
this.moveDownBtn.Location = new System.Drawing.Point(314, 40);
this.moveDownBtn.Name = "moveDownBtn";
this.moveDownBtn.Size = new System.Drawing.Size(30, 17);
this.moveDownBtn.TabIndex = 5;
this.moveDownBtn.UseVisualStyleBackColor = false;
moveDownBtn.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
moveDownBtn.BackColor = System.Drawing.Color.Transparent;
moveDownBtn.BackgroundImage = Properties.Resources.move_down;
moveDownBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
moveDownBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
moveDownBtn.ForeColor = System.Drawing.SystemColors.Control;
moveDownBtn.Location = new System.Drawing.Point(314, 40);
moveDownBtn.Name = "moveDownBtn";
moveDownBtn.Size = new System.Drawing.Size(30, 17);
moveDownBtn.TabIndex = 5;
moveDownBtn.UseVisualStyleBackColor = false;
//
// moveFirstBtn
//
this.moveFirstBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.moveFirstBtn.BackColor = System.Drawing.Color.Transparent;
this.moveFirstBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveFirstBtn.BackgroundImage")));
this.moveFirstBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.moveFirstBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.moveFirstBtn.ForeColor = System.Drawing.SystemColors.Control;
this.moveFirstBtn.Location = new System.Drawing.Point(314, 3);
this.moveFirstBtn.Name = "moveFirstBtn";
this.moveFirstBtn.Size = new System.Drawing.Size(30, 17);
this.moveFirstBtn.TabIndex = 5;
this.moveFirstBtn.UseVisualStyleBackColor = false;
moveFirstBtn.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
moveFirstBtn.BackColor = System.Drawing.Color.Transparent;
moveFirstBtn.BackgroundImage = Properties.Resources.move_first;
moveFirstBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
moveFirstBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
moveFirstBtn.ForeColor = System.Drawing.SystemColors.Control;
moveFirstBtn.Location = new System.Drawing.Point(314, 3);
moveFirstBtn.Name = "moveFirstBtn";
moveFirstBtn.Size = new System.Drawing.Size(30, 17);
moveFirstBtn.TabIndex = 5;
moveFirstBtn.UseVisualStyleBackColor = false;
//
// moveLastBtn
//
this.moveLastBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.moveLastBtn.BackColor = System.Drawing.Color.Transparent;
this.moveLastBtn.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("moveLastBtn.BackgroundImage")));
this.moveLastBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.moveLastBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.moveLastBtn.ForeColor = System.Drawing.SystemColors.Control;
this.moveLastBtn.Location = new System.Drawing.Point(314, 63);
this.moveLastBtn.Name = "moveLastBtn";
this.moveLastBtn.Size = new System.Drawing.Size(30, 17);
this.moveLastBtn.TabIndex = 5;
this.moveLastBtn.UseVisualStyleBackColor = false;
moveLastBtn.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
moveLastBtn.BackColor = System.Drawing.Color.Transparent;
moveLastBtn.BackgroundImage = Properties.Resources.move_last;
moveLastBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
moveLastBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
moveLastBtn.ForeColor = System.Drawing.SystemColors.Control;
moveLastBtn.Location = new System.Drawing.Point(314, 63);
moveLastBtn.Name = "moveLastBtn";
moveLastBtn.Size = new System.Drawing.Size(30, 17);
moveLastBtn.TabIndex = 5;
moveLastBtn.UseVisualStyleBackColor = false;
//
// ProcessBookControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.SystemColors.ControlLight;
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.Controls.Add(this.moveLastBtn);
this.Controls.Add(this.moveDownBtn);
this.Controls.Add(this.moveFirstBtn);
this.Controls.Add(this.moveUpBtn);
this.Controls.Add(this.cancelBtn);
this.Controls.Add(this.statusLbl);
this.Controls.Add(this.etaLbl);
this.Controls.Add(this.remainingTimeLbl);
this.Controls.Add(this.progressBar1);
this.Controls.Add(this.bookInfoLbl);
this.Controls.Add(this.pictureBox1);
this.Margin = new System.Windows.Forms.Padding(4, 2, 4, 2);
this.Name = "ProcessBookControl";
this.Size = new System.Drawing.Size(375, 86);
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
BackColor = System.Drawing.SystemColors.ControlLight;
BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
Controls.Add(moveLastBtn);
Controls.Add(moveDownBtn);
Controls.Add(moveFirstBtn);
Controls.Add(moveUpBtn);
Controls.Add(cancelBtn);
Controls.Add(statusLbl);
Controls.Add(etaLbl);
Controls.Add(remainingTimeLbl);
Controls.Add(progressBar1);
Controls.Add(bookInfoLbl);
Controls.Add(pictureBox1);
Margin = new System.Windows.Forms.Padding(4, 2, 4, 2);
Name = "ProcessBookControl";
Size = new System.Drawing.Size(375, 86);
((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
ResumeLayout(false);
PerformLayout();
}

View File

@@ -12,10 +12,10 @@ namespace LibationWinForms.ProcessQueue
private readonly int ProgressBarDistanceFromEdge;
private object? m_OldContext;
private static Color FailedColor { get; } = Color.LightCoral;
private static Color CancelledColor { get; } = Color.Khaki;
private static Color FailedColor => Application.IsDarkModeEnabled ? Color.FromArgb(0x50, 0x27, 0x27) : Color.LightCoral;
private static Color CancelledColor => Application.IsDarkModeEnabled ? Color.FromArgb(0x4e, 0x4b, 0x15) : Color.Khaki;
private static Color QueuedColor { get; } = SystemColors.Control;
private static Color SuccessColor { get; } = Color.PaleGreen;
private static Color SuccessColor => Application.IsDarkModeEnabled ? Color.FromArgb(0x1c, 0x3e, 0x20) : Color.PaleGreen;
public ProcessBookControl()
{
@@ -23,6 +23,10 @@ namespace LibationWinForms.ProcessQueue
remainingTimeLbl.Visible = false;
progressBar1.Visible = false;
etaLbl.Visible = false;
moveDownBtn.BackgroundImage = Application.IsDarkModeEnabled ? Properties.Resources.move_down_dark : Properties.Resources.move_down;
moveUpBtn.BackgroundImage = Application.IsDarkModeEnabled ? Properties.Resources.move_up_dark : Properties.Resources.move_up;
moveFirstBtn.BackgroundImage = Application.IsDarkModeEnabled ? Properties.Resources.move_first_dark : Properties.Resources.move_first;
moveLastBtn.BackgroundImage = Application.IsDarkModeEnabled ? Properties.Resources.move_last_dark : Properties.Resources.move_last;
CancelBtnDistanceFromEdge = Width - cancelBtn.Location.X;
ProgressBarDistanceFromEdge = Width - progressBar1.Location.X - progressBar1.Width;

View File

File diff suppressed because it is too large Load Diff

View File

@@ -31,7 +31,11 @@ internal partial class ProcessQueueControl : UserControl
virtualFlowControl2.ButtonClicked += VirtualFlowControl2_ButtonClicked;
virtualFlowControl2.DataContext = ViewModel.Queue;
queueNumberLbl.Image = Application.IsDarkModeEnabled ? Properties.Resources.queue_queued_dark : Properties.Resources.queue_queued;
errorNumberLbl.Image = Application.IsDarkModeEnabled ? Properties.Resources.queue_error_dark : Properties.Resources.queue_error;
completedNumberLbl.Image = Application.IsDarkModeEnabled ? Properties.Resources.queue_completed_dark : Properties.Resources.queue_completed;
logDGV.EnableHeadersVisualStyles = !Application.IsDarkModeEnabled;
ViewModel.PropertyChanged += ProcessQueue_PropertyChanged;
ViewModel.LogEntries.CollectionChanged += LogEntries_CollectionChanged;
ProcessQueue_PropertyChanged(this, new PropertyChangedEventArgs(null));

View File

@@ -46,10 +46,11 @@ namespace LibationWinForms
LibationUiBase.Forms.MessageBoxBase.ShowAsyncImpl = ShowMessageBox;
// do this as soon as possible (post-config)
RunSetupIfNeededAsync(config).Wait();
RunSetupIfNeededAsync(config);
// most migrations go in here
LibationScaffolding.RunPostConfigMigrations(config);
SetThemeColor(config);
// migrations which require Forms or are long-running
RunWindowsOnlyMigrations(config);
@@ -117,7 +118,19 @@ namespace LibationWinForms
}
#endregion;
private static async Task RunSetupIfNeededAsync(Configuration config)
private static void SetThemeColor(Configuration config)
{
var theme = config.ThemeVariant switch
{
Configuration.Theme.Light => SystemColorMode.Classic,
Configuration.Theme.Dark => SystemColorMode.Dark,
_ => SystemColorMode.System,
};
Application.SetColorMode(theme);
}
private static void RunSetupIfNeededAsync(Configuration config)
{
var setup = new LibationSetup(config.LibationFiles)
{
@@ -125,7 +138,7 @@ namespace LibationWinForms
SelectFolderPrompt = SelectInstallLocation
};
if (!await setup.RunSetupIfNeededAsync())
if (!setup.RunSetupIfNeededAsync().GetAwaiter().GetResult())
{
MessageBox.Show("Initial set up cancelled.", "Cancelled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
Application.Exit();

View File

@@ -19,7 +19,7 @@ namespace LibationWinForms.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -70,6 +70,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap cheers_dark {
get {
object obj = ResourceManager.GetObject("cheers_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -110,6 +120,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Dolby_Atmos_Vertical_80_dark {
get {
object obj = ResourceManager.GetObject("Dolby_Atmos_Vertical_80_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -123,29 +143,9 @@ namespace LibationWinForms.Properties {
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap edit_64x64 {
internal static System.Drawing.Bitmap edit_25x25_dark {
get {
object obj = ResourceManager.GetObject("edit_64x64", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap edit_tags_25x25 {
get {
object obj = ResourceManager.GetObject("edit_tags_25x25", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap edit_tags_50x50 {
get {
object obj = ResourceManager.GetObject("edit_tags_50x50", resourceCulture);
object obj = ResourceManager.GetObject("edit_25x25_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
@@ -160,6 +160,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap error_dark {
get {
object obj = ResourceManager.GetObject("error_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -170,6 +180,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap import_16x16_dark {
get {
object obj = ResourceManager.GetObject("import_16x16_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -180,6 +200,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap liberate_green_dark {
get {
object obj = ResourceManager.GetObject("liberate_green_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -190,6 +220,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap liberate_green_pdf_no_dark {
get {
object obj = ResourceManager.GetObject("liberate_green_pdf_no_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -200,6 +240,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap liberate_green_pdf_yes_dark {
get {
object obj = ResourceManager.GetObject("liberate_green_pdf_yes_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -210,6 +260,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap liberate_red_dark {
get {
object obj = ResourceManager.GetObject("liberate_red_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -220,6 +280,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap liberate_red_pdf_no_dark {
get {
object obj = ResourceManager.GetObject("liberate_red_pdf_no_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -230,6 +300,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap liberate_red_pdf_yes_dark {
get {
object obj = ResourceManager.GetObject("liberate_red_pdf_yes_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -240,6 +320,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap liberate_yellow_dark {
get {
object obj = ResourceManager.GetObject("liberate_yellow_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -250,6 +340,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap liberate_yellow_pdf_no_dark {
get {
object obj = ResourceManager.GetObject("liberate_yellow_pdf_no_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -260,6 +360,16 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap liberate_yellow_pdf_yes_dark {
get {
object obj = ResourceManager.GetObject("liberate_yellow_pdf_yes_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -270,6 +380,96 @@ namespace LibationWinForms.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap minus_dark {
get {
object obj = ResourceManager.GetObject("minus_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap move_down {
get {
object obj = ResourceManager.GetObject("move_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap move_down_dark {
get {
object obj = ResourceManager.GetObject("move_down_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap move_first {
get {
object obj = ResourceManager.GetObject("move_first", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap move_first_dark {
get {
object obj = ResourceManager.GetObject("move_first_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap move_last {
get {
object obj = ResourceManager.GetObject("move_last", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap move_last_dark {
get {
object obj = ResourceManager.GetObject("move_last_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap move_up {
get {
object obj = ResourceManager.GetObject("move_up", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap move_up_dark {
get {
object obj = ResourceManager.GetObject("move_up_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -279,5 +479,75 @@ namespace LibationWinForms.Properties {
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap plus_dark {
get {
object obj = ResourceManager.GetObject("plus_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap queue_completed {
get {
object obj = ResourceManager.GetObject("queue_completed", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap queue_completed_dark {
get {
object obj = ResourceManager.GetObject("queue_completed_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap queue_error {
get {
object obj = ResourceManager.GetObject("queue_error", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap queue_error_dark {
get {
object obj = ResourceManager.GetObject("queue_error_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap queue_queued {
get {
object obj = ResourceManager.GetObject("queue_queued", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap queue_queued_dark {
get {
object obj = ResourceManager.GetObject("queue_queued_dark", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@@ -130,8 +130,8 @@
<data name="liberate_yellow" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_yellow.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="edit_64x64" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\edit_64x64.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="edit_25x25" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\edit_25x25.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="default_cover_300x300" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\img-coverart-prod-unavailable_300x300.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
@@ -142,15 +142,9 @@
<data name="liberate_red" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_red.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="edit_tags_50x50" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\edit-tags-50x50.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="liberate_green_pdf_yes" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_green_pdf_yes.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="edit_25x25" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\edit_25x25.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="plus" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\plus.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@@ -178,10 +172,97 @@
<data name="liberate_yellow_pdf_no" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_yellow_pdf_no.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="edit_tags_25x25" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\edit-tags-25x25.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Dolby_Atmos_Vertical_80" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Dolby_Atmos_Vertical_80.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="liberate_green_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_green_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="liberate_green_pdf_no_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_green_pdf_no_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="liberate_green_pdf_yes_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_green_pdf_yes_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="liberate_red_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_red_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="liberate_red_pdf_no_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_red_pdf_no_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="liberate_red_pdf_yes_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_red_pdf_yes_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="plus_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\plus_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="minus_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\minus_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="liberate_yellow_pdf_yes_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_yellow_pdf_yes_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="liberate_yellow_pdf_no_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_yellow_pdf_no_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="liberate_yellow_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\liberate_yellow_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Dolby_Atmos_Vertical_80_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Dolby_Atmos_Vertical_80_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="cheers_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\cheers_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="edit_25x25_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\edit_25x25_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="error_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\error_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="import_16x16_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\import_16x16_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="move_first" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\move_first.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="move_first_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\move_first_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="move_up" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\move_up.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="move_up_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\move_up_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="move_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\move_down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="move_down_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\move_down_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="move_last" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\move_last.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="move_last_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\move_last_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="queue_completed" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\queue_completed.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="queue_completed_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\queue_completed_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="queue_error" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\queue_error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="queue_error_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\queue_error_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="queue_queued" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\queue_queued.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="queue_queued_dark" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\queue_queued_dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 573 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 747 B

After

Width:  |  Height:  |  Size: 588 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 B

After

Width:  |  Height:  |  Size: 433 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Some files were not shown because too many files have changed in this diff Show More