Compare commits

...

34 Commits

Author SHA1 Message Date
Robert McRackan
b479096fc2 Added logging. Bug fix in MFA login form 2021-07-25 16:49:07 -04:00
rmcrackan
ad09d36588 Merge pull request #69 from Mbucari/master
Added logging of download license.
2021-07-24 19:56:55 -04:00
Mbucari
1a9c0188a4 Update AaxcDownloadConverter.cs 2021-07-24 16:12:11 -06:00
Mbucari
ca75b55da4 Merge branch 'rmcrackan:master' into master 2021-07-24 15:12:12 -06:00
Michael Bucari-Tovo
285b1e7b45 Removed dll. 2021-07-24 15:11:50 -06:00
Michael Bucari-Tovo
6912a499d0 Moved download licnse from debug log to verbose log. 2021-07-24 15:11:05 -06:00
Robert McRackan
4e70365150 increm ver # 2021-07-24 16:27:17 -04:00
Robert McRackan
811a95aedf After LogLevel changed in settings: warn if Verbose logging level 2021-07-24 16:26:50 -04:00
Michael Bucari-Tovo
20971124ab Add DLL temporarily. 2021-07-24 11:29:49 -06:00
Michael Bucari-Tovo
fa66a361dc Add logging of download license in DebugInfo 2021-07-24 11:28:58 -06:00
Robert McRackan
61d7f5a5cb version 2021-07-22 22:44:07 -04:00
Robert McRackan
f8c788297e Better error info when offering to skip problematic book (issue #65) 2021-07-22 22:08:36 -04:00
Robert McRackan
79e5545fd3 config bug fix 2021-07-22 14:08:15 -04:00
Robert McRackan
b4def2e2d6 Remember screen position. Issue #61 2021-07-21 23:13:14 -04:00
Robert McRackan
281d615649 Merge branch 'master' of https://github.com/rmcrackan/Libation 2021-07-21 14:45:22 -04:00
Robert McRackan
c2c6a31716 Remove "advanced settings". Too error prone 2021-07-21 14:43:59 -04:00
rmcrackan
391f1f387b Update README.md 2021-07-21 14:18:45 -04:00
Robert McRackan
206890b8f3 settings folders need read-only textbox 2021-07-21 14:12:35 -04:00
Robert McRackan
9aa31338d6 New locale: Spain 2021-07-21 13:48:52 -04:00
Robert McRackan
35fe3ae786 New setting: dynamically change log level without app restart 2021-07-21 13:38:22 -04:00
Robert McRackan
b6fe3ae009 version 2021-07-21 07:10:26 -04:00
Robert McRackan
6ba8c0ca91 Decrypt form: remove debug window 2021-07-21 07:10:01 -04:00
Robert McRackan
01de928b7a Better validation when writing to decrypt log UI 2021-07-20 15:19:01 -04:00
Robert McRackan
0a54f8d881 v5.2.1 2021-07-20 14:47:15 -04:00
Robert McRackan
d31121e307 Bug fix to address #59 2021-07-20 14:43:08 -04:00
Robert McRackan
b86bd76726 New button in settings to open file logs folder 2021-07-20 14:37:32 -04:00
Robert McRackan
c49edbc77b Better error logging. MessageBoxAlertAdmin to make it easier for users to report errors 2021-07-20 14:27:27 -04:00
Robert McRackan
1ba54a74af rename basic/advanced settings in menu
*  basic => Settings
* advanced => Move settings files
2021-07-19 23:00:25 -04:00
Robert McRackan
9de08a332f v5.2.0 2021-07-19 14:53:10 -04:00
Robert McRackan
c9b434daed Overhaul of installation workflow per issue #36 2021-07-19 14:52:34 -04:00
rmcrackan
730484c28c Merge pull request #56 from Mbucari/master
Added MP3 support to settings.
2021-07-18 21:03:56 -04:00
Michael Bucari-Tovo
1a48dbe560 Fixed log. 2021-07-18 17:28:37 -06:00
Michael Bucari-Tovo
7df8c7427c Added MP3 conversion option. 2021-07-18 17:18:35 -06:00
Robert McRackan
8997f52505 replace dir selection controls in both settings dialogs with new ctrl.s 2021-07-18 17:48:15 -04:00
40 changed files with 1498 additions and 1285 deletions

View File

@@ -2,12 +2,18 @@
using Dinah.Core;
using Dinah.Core.Diagnostics;
using Dinah.Core.IO;
using Dinah.Core.Logging;
using Dinah.Core.StepRunner;
using System;
using System.IO;
namespace AaxDecrypter
{
public enum OutputFormat
{
Mp4a,
Mp3
}
public class AaxcDownloadConverter
{
public event EventHandler<AppleTags> RetrievedTags;
@@ -21,6 +27,7 @@ namespace AaxDecrypter
private DownloadLicense downloadLicense { get; }
private AaxFile aaxFile;
private byte[] coverArt;
private OutputFormat OutputFormat;
private StepSequence steps { get; }
private NetworkFileStreamPersister nfsPersister;
@@ -28,11 +35,12 @@ namespace AaxDecrypter
private string jsonDownloadState => Path.Combine(cacheDir, Path.GetFileNameWithoutExtension(OutputFileName) + ".json");
private string tempFile => PathLib.ReplaceExtension(jsonDownloadState, ".aaxc");
public AaxcDownloadConverter(string outFileName, string cacheDirectory, DownloadLicense dlLic)
public AaxcDownloadConverter(string outFileName, string cacheDirectory, DownloadLicense dlLic, OutputFormat outputFormat)
{
ArgumentValidator.EnsureNotNullOrWhiteSpace(outFileName, nameof(outFileName));
OutputFileName = PathLib.ReplaceExtension(outFileName, ".m4b");
OutputFileName = outFileName;
var outDir = Path.GetDirectoryName(OutputFileName);
if (!Directory.Exists(outDir))
throw new ArgumentNullException(nameof(outDir), "Directory does not exist");
if (File.Exists(OutputFileName))
@@ -43,10 +51,13 @@ namespace AaxDecrypter
cacheDir = cacheDirectory;
downloadLicense = ArgumentValidator.EnsureNotNull(dlLic, nameof(dlLic));
OutputFormat = outputFormat;
Serilog.Log.Logger.Verbose("Download License. {@DebugInfo}", downloadLicense);
steps = new StepSequence
{
Name = "Download and Convert Aaxc To M4b",
Name = "Download and Convert Aaxc To " + (outputFormat == OutputFormat.Mp4a ? "M4b" : "Mp3"),
["Step 1: Get Aaxc Metadata"] = Step1_GetMetadata,
["Step 2: Download Decrypted Audiobook"] = Step2_DownloadAndCombine,
@@ -125,7 +136,6 @@ namespace AaxDecrypter
public bool Step2_DownloadAndCombine()
{
OutputFormat format = OutputFormat.Mp4a;
DecryptProgressUpdate?.Invoke(this, 0);
@@ -134,15 +144,20 @@ namespace AaxDecrypter
FileStream outFile = File.OpenWrite(OutputFileName);
aaxFile.SetDecryptionKey(downloadLicense.AudibleKey, downloadLicense.AudibleIV);
aaxFile.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate;
var decryptionResult = aaxFile.DecryptAaxc(outFile, downloadLicense.AudibleKey, downloadLicense.AudibleIV, format, downloadLicense.ChapterInfo);
var decryptionResult = OutputFormat == OutputFormat.Mp4a ? aaxFile.ConvertToMp4a(outFile, downloadLicense.ChapterInfo) : aaxFile.ConvertToMp3(outFile);
aaxFile.ConversionProgressUpdate -= AaxFile_ConversionProgressUpdate;
aaxFile.Close();
downloadLicense.ChapterInfo = aaxFile.Chapters;
if (decryptionResult == ConversionResult.NoErrorsDetected
&& coverArt is not null
&& format == OutputFormat.Mp4a)
&& OutputFormat == OutputFormat.Mp4a)
{
//This handles a special case where the aaxc file doesn't contain cover art and
//Libation downloaded it instead (Animal Farm). Currently only works for Mp4a files.

View File

@@ -71,7 +71,8 @@ namespace DtoImporterService
foreach (var p in people)
{
var person = DbContext.Contributors.Local.SingleOrDefault(c => c.Name == p.Name);
// Should be 'Single' not 'First'. A user had a duplicate get in somehow though so I'm now using 'First' defensively
var person = DbContext.Contributors.Local.FirstOrDefault(c => c.Name == p.Name);
if (person == null)
{
person = DbContext.Contributors.Add(new Contributor(p.Name, p.Asin)).Entity;

View File

@@ -67,9 +67,29 @@ namespace FileLiberator
{
validate(libraryBook);
Serilog.Log.Logger.Debug("Trying to debug mysterious null ref exception {@DebugInfo}", new {
libraryBookIsNull = libraryBook is null,
BookIsNull = libraryBook?.Book is null,
libraryBook?.Book?.Locale,
libraryBook?.Book?.AudibleProductId,
AccountLength = libraryBook?.Account?.Length
});
var api = await InternalUtilities.AudibleApiActions.GetApiAsync(libraryBook.Account, libraryBook.Book.Locale);
Serilog.Log.Logger.Debug("Trying to debug mysterious null ref exception {@DebugInfo}", new { apiIsNull = api is null });
var contentLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId);
Serilog.Log.Logger.Debug("Trying to debug mysterious null ref exception {@DebugInfo}", new {
contentLicIsNull = contentLic is null,
contentMetadataIsNull = contentLic?.ContentMetadata is null,
voucherIsNull = contentLic?.Voucher is null,
keyIsNull = contentLic?.Voucher?.Key is null,
keyLength = contentLic?.Voucher?.Key?.Length,
ivIsNull = contentLic?.Voucher?.Iv is null,
ivLength = contentLic?.Voucher?.Iv?.Length,
});
var aaxcDecryptDlLic = new DownloadLicense
(
@@ -87,8 +107,20 @@ namespace FileLiberator
aaxcDecryptDlLic.ChapterInfo.AddChapter(chap.Title, TimeSpan.FromMilliseconds(chap.LengthMs));
}
var proposedOutputFile = Path.Combine(destinationDir, $"{PathLib.ToPathSafeString(libraryBook.Book.Title)} [{libraryBook.Book.AudibleProductId}].m4b");
aaxcDownloader = new AaxcDownloadConverter(proposedOutputFile, cacheDir, aaxcDecryptDlLic) { AppName = "Libation" };
var format = Configuration.Instance.DecryptToLossy ? OutputFormat.Mp3 : OutputFormat.Mp4a;
var extension = format switch
{
OutputFormat.Mp4a => "m4b",
OutputFormat.Mp3 => "mp3",
_ => throw new NotImplementedException(),
};
var proposedOutputFile = Path.Combine(destinationDir, $"{PathLib.ToPathSafeString(libraryBook.Book.Title)} [{libraryBook.Book.AudibleProductId}].{extension}");
aaxcDownloader = new AaxcDownloadConverter(proposedOutputFile, cacheDir, aaxcDecryptDlLic, format) { AppName = "Libation" };
aaxcDownloader.DecryptProgressUpdate += (s, progress) => UpdateProgress?.Invoke(this, progress);
aaxcDownloader.DecryptTimeRemaining += (s, remaining) => UpdateRemainingTime?.Invoke(this, remaining);
aaxcDownloader.RetrievedCoverArt += AaxcDownloader_RetrievedCoverArt;

View File

@@ -28,16 +28,16 @@ namespace FileManager
public static AudibleFileStorage AAXC { get; } = new AaxcFileStorage();
public static AudibleFileStorage PDF { get; } = new PdfFileStorage();
public static string DownloadsInProgress => Directory.CreateDirectory(Path.Combine(Configuration.Instance.DownloadsInProgressEnum, "DownloadsInProgress")).FullName;
public static string DownloadsInProgress => Directory.CreateDirectory(Path.Combine(Configuration.Instance.InProgress, "DownloadsInProgress")).FullName;
public static string DecryptInProgress => Directory.CreateDirectory(Path.Combine(Configuration.Instance.DecryptInProgressEnum, "DecryptInProgress")).FullName;
public static string DecryptInProgress => Directory.CreateDirectory(Path.Combine(Configuration.Instance.InProgress, "DecryptInProgress")).FullName;
public static string BooksDirectory
{
get
{
if (string.IsNullOrWhiteSpace(Configuration.Instance.Books))
Configuration.Instance.Books = Path.Combine(Configuration.Instance.LibationFiles, "Books");
Configuration.Instance.Books = Path.Combine(Configuration.UserProfile, "Books");
return Directory.CreateDirectory(Configuration.Instance.Books).FullName;
}
}

View File

@@ -4,60 +4,138 @@ using System.ComponentModel;
using System.IO;
using System.Linq;
using Dinah.Core;
using Dinah.Core.Logging;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Serilog;
using Serilog.Events;
namespace FileManager
{
public class Configuration
{
// settings will be persisted when all are true
// - property (not field)
// - string
// - public getter
// - public setter
public bool LibationSettingsAreValid
=> File.Exists(APPSETTINGS_JSON)
&& SettingsFileIsValid(SettingsFilePath);
#region // properties to test reflection
/*
// field should NOT be populated
public string TestField;
// int should NOT be populated
public int TestInt { get; set; }
// read-only should NOT be populated
public string TestGet { get; } // get only: should NOT get auto-populated
// set-only should NOT be populated
public string TestSet { private get; set; }
public static bool SettingsFileIsValid(string settingsFile)
{
if (!Directory.Exists(Path.GetDirectoryName(settingsFile)) || !File.Exists(settingsFile))
return false;
// get and set: SHOULD be auto-populated
public string TestGetSet { get; set; }
*/
#endregion
var pDic = new PersistentDictionary(settingsFile, isReadOnly: true);
var booksDir = pDic.GetString(nameof(Books));
if (booksDir is null || !Directory.Exists(booksDir))
return false;
if (string.IsNullOrWhiteSpace(pDic.GetString(nameof(InProgress))))
return false;
return true;
}
#region persistent configuration settings/values
// note: any potential file manager static ctors can't compensate if storage dir is changed at run time via settings. this is partly bad architecture. but the side effect is desirable. if changing LibationFiles location: restart app
// default setting and directory creation occur in class responsible for files.
// config class is only responsible for path. not responsible for setting defaults, dir validation, or dir creation
// exceptions: appsettings.json, LibationFiles dir, Settings.json
private PersistentDictionary persistentDictionary;
public bool FilesExist
=> File.Exists(APPSETTINGS_JSON)
&& File.Exists(SettingsFilePath)
&& Directory.Exists(LibationFiles)
&& Directory.Exists(Books);
public object GetObject(string propertyName) => persistentDictionary.GetObject(propertyName);
public void SetObject(string propertyName, object newValue) => persistentDictionary.SetNonString(propertyName, newValue);
/// <summary>WILL ONLY set if already present. WILL NOT create new</summary>
/// <returns>Value was changed</returns>
public bool SetWithJsonPath(string jsonPath, string propertyName, string newValue, bool suppressLogging = false)
=> persistentDictionary.SetWithJsonPath(jsonPath, propertyName, newValue, suppressLogging);
public string SettingsFilePath => Path.Combine(LibationFiles, "Settings.json");
public static string GetDescription(string propertyName)
{
var attribute = typeof(Configuration)
.GetProperty(propertyName)
?.GetCustomAttributes(typeof(DescriptionAttribute), true)
.SingleOrDefault()
as DescriptionAttribute;
return attribute?.Description;
}
public bool Exists(string propertyName) => persistentDictionary.Exists(propertyName);
#region MainForm: X, Y, Width, Height, MainFormIsMaximized
public int MainFormX
{
get => persistentDictionary.GetNonString<int>(nameof(MainFormX));
set => persistentDictionary.SetNonString(nameof(MainFormX), value);
}
public int MainFormY
{
get => persistentDictionary.GetNonString<int>(nameof(MainFormY));
set => persistentDictionary.SetNonString(nameof(MainFormY), value);
}
public int MainFormWidth
{
get => persistentDictionary.GetNonString<int>(nameof(MainFormWidth));
set => persistentDictionary.SetNonString(nameof(MainFormWidth), value);
}
public int MainFormHeight
{
get => persistentDictionary.GetNonString<int>(nameof(MainFormHeight));
set => persistentDictionary.SetNonString(nameof(MainFormHeight), value);
}
public bool MainFormIsMaximized
{
get => persistentDictionary.GetNonString<bool>(nameof(MainFormIsMaximized));
set => persistentDictionary.SetNonString(nameof(MainFormIsMaximized), value);
}
#endregion
[Description("Location for book storage. Includes destination of newly liberated books")]
public string Books
{
get => persistentDictionary.GetString(nameof(Books));
set => persistentDictionary.Set(nameof(Books), value);
set => persistentDictionary.SetString(nameof(Books), value);
}
#region known directories
public const string WIN_TEMP_LABEL = "WinTemp";
public const string LIBATION_FILES_LABEL = "LibationFiles";
public const string USER_PROFILE_LABEL = "UserProfile";
public static string AppDir_Relative => @".\LibationFiles";
// temp/working dir(s) should be outside of dropbox
[Description("Temporary location of files while they're in process of being downloaded and decrypted.\r\nWhen decryption is complete, the final file will be in Books location\r\nRecommend not using a folder which is backed up real time. Eg: Dropbox, iCloud, Google Drive")]
public string InProgress
{
get => persistentDictionary.GetString(nameof(InProgress));
set => persistentDictionary.SetString(nameof(InProgress), value);
}
[Description("Allow Libation for fix up audiobook metadata?")]
public bool AllowLibationFixup
{
get => persistentDictionary.GetNonString<bool>(nameof(AllowLibationFixup));
set => persistentDictionary.SetNonString(nameof(AllowLibationFixup), value);
}
[Description("Decrypt to lossy format?")]
public bool DecryptToLossy
{
get => persistentDictionary.GetNonString<bool>(nameof(DecryptToLossy));
set => persistentDictionary.SetNonString(nameof(DecryptToLossy), value);
}
#endregion
#region known directories
public static string AppDir_Relative => $@".\{LIBATION_FILES_KEY}";
public static string AppDir_Absolute => Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Exe.FileLocationOnDisk), LIBATION_FILES_KEY));
public static string MyDocs => Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "LibationFiles"));
public static string MyDocs => Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Libation"));
public static string WinTemp => Path.GetFullPath(Path.Combine(Path.GetTempPath(), "Libation"));
public static string UserProfile => Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Libation"));
@@ -88,7 +166,8 @@ namespace FileManager
(KnownDirectories.AppDir, () => AppDir_Relative),
(KnownDirectories.WinTemp, () => WinTemp),
(KnownDirectories.MyDocs, () => MyDocs),
// this is important to not let very early calls try to accidentally load LibationFiles too early
// this is important to not let very early calls try to accidentally load LibationFiles too early.
// also, keep this at bottom of this list
(KnownDirectories.LibationFiles, () => libationFilesPathCache)
};
public static string GetKnownDirectoryPath(KnownDirectories directory)
@@ -102,52 +181,78 @@ namespace FileManager
if (string.IsNullOrWhiteSpace(directory))
return KnownDirectories.None;
var dirFunc = directoryOptionsPaths.SingleOrDefault(dirFunc => dirFunc.getPathFunc() == directory);
// 'First' instead of 'Single' because LibationFiles could match other directories. eg: default value of LibationFiles == UserProfile.
// since it's a list, order matters and non-LibationFiles will be returned first
var dirFunc = directoryOptionsPaths.FirstOrDefault(dirFunc => dirFunc.getPathFunc() == directory);
return dirFunc == default ? KnownDirectories.None : dirFunc.directory;
}
#endregion
// default setting and directory creation occur in class responsible for files.
// config class is only responsible for path. not responsible for setting defaults, dir validation, or dir creation
// exceptions: appsettings.json, LibationFiles dir, Settings.json
// temp/working dir(s) should be outside of dropbox
[Description("Temporary location of files while they're in process of being downloaded and decrypted.\r\nWhen decryption is complete, the final file will be in Books location\r\nRecommend not using a folder which is backed up real time. Eg: Dropbox, iCloud, Google Drive")]
public string InProgress
#region logging
private IConfigurationRoot configuration;
public void ConfigureLogging()
{
get => persistentDictionary.GetString(nameof(InProgress));
set => persistentDictionary.Set(nameof(InProgress), value);
//// with code. also persists to Settings.json
//SetWithJsonPath("Serilog.WriteTo[1].Args", "path", logPath, true);
//// hack which achieves the same, in memory only
//configuration["Serilog:WriteTo:1:Args:path"] = logPath;
configuration = new ConfigurationBuilder()
.AddJsonFile(SettingsFilePath, optional: false, reloadOnChange: true)
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
}
[Description("Temporary location of files while they're in process of being downloaded.\r\nWhen download is complete, the final file will be in [LibationFiles]\\DownloadsFinal")]
public string DownloadsInProgressEnum
[Description("The importance of a log event")]
public LogEventLevel LogLevel
{
get => persistentDictionary.GetString(nameof(DownloadsInProgressEnum));
set => persistentDictionary.Set(nameof(DownloadsInProgressEnum), value);
}
get
{
try
{
var logLevelStr = persistentDictionary.GetStringFromJsonPath("Serilog", "MinimumLevel");
var logLevelEnum = Enum<LogEventLevel>.Parse(logLevelStr);
return logLevelEnum;
}
catch
{
return LogEventLevel.Information;
}
}
set
{
var valueWasChanged = persistentDictionary.SetWithJsonPath("Serilog", "MinimumLevel", value.ToString());
if (!valueWasChanged)
{
Log.Logger.Information("LogLevel.set attempt. No change");
return;
}
// temp/working dir(s) should be outside of dropbox
[Description("Temporary location of files while they're in process of being decrypted.\r\nWhen decryption is complete, the final file will be in Books location")]
public string DecryptInProgressEnum
{
get => persistentDictionary.GetString(nameof(DecryptInProgressEnum));
set => persistentDictionary.Set(nameof(DecryptInProgressEnum), value);
}
configuration.Reload();
[Description("Allow Libation for fix up audiobook metadata?")]
public bool AllowLibationFixup
{
get => persistentDictionary.Get<bool>(nameof(AllowLibationFixup));
set => persistentDictionary.Set(nameof(AllowLibationFixup), value);
Log.Logger.Information("Updated LogLevel MinimumLevel. {@DebugInfo}", new
{
LogLevel_Verbose_Enabled = Log.Logger.IsVerboseEnabled(),
LogLevel_Debug_Enabled = Log.Logger.IsDebugEnabled(),
LogLevel_Information_Enabled = Log.Logger.IsInformationEnabled(),
LogLevel_Warning_Enabled = Log.Logger.IsWarningEnabled(),
LogLevel_Error_Enabled = Log.Logger.IsErrorEnabled(),
LogLevel_Fatal_Enabled = Log.Logger.IsFatalEnabled()
});
}
}
// note: any potential file manager static ctors can't compensate if storage dir is changed at run time via settings. this is partly bad architecture. but the side effect is desirable. if changing LibationFiles location: restart app
#endregion
// singleton stuff
public static Configuration Instance { get; } = new Configuration();
#region singleton stuff
public static Configuration Instance { get; } = new Configuration();
private Configuration() { }
#endregion
private const string APPSETTINGS_JSON = "appsettings.json";
// this is the key in appsettings. The string happens to match the metadirectory name but separate concern. keep separate
#region LibationFiles
private const string APPSETTINGS_JSON = "appsettings.json";
private const string LIBATION_FILES_KEY = "LibationFiles";
[Description("Location for storage of program-created files")]
@@ -158,12 +263,19 @@ namespace FileManager
if (libationFilesPathCache is not null)
return libationFilesPathCache;
// must write here before SettingsFilePath in next step reads cache
// FIRST: must write here before SettingsFilePath in next step reads cache
libationFilesPathCache = getLiberationFilesSettingFromJson();
// load json values into memory. create settings if not exists
// SECOND. before setting to json file with SetWithJsonPath, PersistentDictionary must exist
persistentDictionary = new PersistentDictionary(SettingsFilePath);
// Config init in Program.ensureSerilogConfig() only happens when serilog setting is first created (prob on 1st run).
// This Set() enforces current LibationFiles every time we restart Libation or redirect LibationFiles
var logPath = Path.Combine(LibationFiles, "Log.log");
bool settingWasChanged = SetWithJsonPath("Serilog.WriteTo[1].Args", "path", logPath, true);
if (settingWasChanged)
configuration?.Reload();
return libationFilesPathCache;
}
}
@@ -205,49 +317,28 @@ namespace FileManager
return valueFinal;
}
public object GetObject(string propertyName) => persistentDictionary.GetObject(propertyName);
public void SetObject(string propertyName, object newValue) => persistentDictionary.Set(propertyName, newValue);
public void SetWithJsonPath(string jsonPath, string propertyName, string newValue) => persistentDictionary.SetWithJsonPath(jsonPath, propertyName, newValue);
public static string GetDescription(string propertyName)
public void SetLibationFiles(string directory)
{
var attribute = typeof(Configuration)
.GetProperty(propertyName)
?.GetCustomAttributes(typeof(DescriptionAttribute), true)
.SingleOrDefault()
as DescriptionAttribute;
return attribute?.Description;
}
public bool TrySetLibationFiles(string directory)
{
// this is WRONG. need to MOVE settings; not DELETE them
//// if moving from default, delete old settings file and dir (if empty)
//if (LibationFiles.EqualsInsensitive(AppDir))
//{
// File.Delete(SettingsFilePath);
// System.Threading.Thread.Sleep(100);
// if (!Directory.EnumerateDirectories(AppDir).Any() && !Directory.EnumerateFiles(AppDir).Any())
// Directory.Delete(AppDir);
//}
libationFilesPathCache = null;
var startingContents = File.ReadAllText(APPSETTINGS_JSON);
var jObj = JObject.Parse(startingContents);
jObj[LIBATION_FILES_KEY] = directory;
var endingContents = JsonConvert.SerializeObject(jObj, Formatting.Indented);
if (startingContents != endingContents)
File.WriteAllText(APPSETTINGS_JSON, endingContents);
if (startingContents == endingContents)
return;
// now it's set in the file again but no settings have moved yet
File.WriteAllText(APPSETTINGS_JSON, endingContents);
return true;
try
{
Log.Logger.Information("Libation files changed {@DebugInfo}", new { APPSETTINGS_JSON, LIBATION_FILES_KEY, directory });
}
catch { }
}
#endregion
}
}

View File

@@ -5,6 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
<PackageReference Include="Octokit" Version="0.50.0" />
<PackageReference Include="Polly" Version="7.2.2" />
</ItemGroup>

View File

@@ -10,14 +10,16 @@ namespace FileManager
public class PersistentDictionary
{
public string Filepath { get; }
public bool IsReadOnly { get; }
// optimize for strings. expectation is most settings will be strings and a rare exception will be something else
private Dictionary<string, string> stringCache { get; } = new Dictionary<string, string>();
private Dictionary<string, object> objectCache { get; } = new Dictionary<string, object>();
public PersistentDictionary(string filepath)
public PersistentDictionary(string filepath, bool isReadOnly = false)
{
Filepath = filepath;
IsReadOnly = isReadOnly;
if (File.Exists(Filepath))
return;
@@ -25,6 +27,9 @@ namespace FileManager
// will create any missing directories, incl subdirectories. if all already exist: no action
Directory.CreateDirectory(Path.GetDirectoryName(filepath));
if (IsReadOnly)
return;
File.WriteAllText(Filepath, "{}");
System.Threading.Thread.Sleep(100);
}
@@ -34,18 +39,20 @@ namespace FileManager
if (!stringCache.ContainsKey(propertyName))
{
var jObject = readFile();
stringCache[propertyName] = jObject.ContainsKey(propertyName) ? jObject[propertyName].Value<string>() : null;
if (!jObject.ContainsKey(propertyName))
return null;
stringCache[propertyName] = jObject[propertyName].Value<string>();
}
return stringCache[propertyName];
}
public T Get<T>(string propertyName)
public T GetNonString<T>(string propertyName)
{
var o = GetObject(propertyName);
if (o is null) return default;
if (o is JToken jt) return jt.Value<T>();
return (T)o;
var obj = GetObject(propertyName);
if (obj is null) return default;
if (obj is JToken jToken) return jToken.Value<T>();
return (T)obj;
}
public object GetObject(string propertyName)
@@ -53,17 +60,43 @@ namespace FileManager
if (!objectCache.ContainsKey(propertyName))
{
var jObject = readFile();
objectCache[propertyName] = jObject.ContainsKey(propertyName) ? jObject[propertyName].Value<object>() : null;
if (!jObject.ContainsKey(propertyName))
return null;
objectCache[propertyName] = jObject[propertyName].Value<object>();
}
return objectCache[propertyName];
}
public string GetStringFromJsonPath(string jsonPath, string propertyName) => GetStringFromJsonPath($"{jsonPath}.{propertyName}");
public string GetStringFromJsonPath(string jsonPath)
{
if (!stringCache.ContainsKey(jsonPath))
{
try
{
var jObject = readFile();
var token = jObject.SelectToken(jsonPath);
if (token is null)
return null;
stringCache[jsonPath] = (string)token;
}
catch
{
return null;
}
}
return stringCache[jsonPath];
}
public bool Exists(string propertyName) => readFile().ContainsKey(propertyName);
private object locker { get; } = new object();
public void Set(string propertyName, string newValue)
public void SetString(string propertyName, string newValue)
{
// only do this check in string cache, NOT object cache
if (stringCache[propertyName] == newValue)
if (stringCache.ContainsKey(propertyName) && stringCache[propertyName] == newValue)
return;
// set cache
@@ -72,7 +105,7 @@ namespace FileManager
writeFile(propertyName, newValue);
}
public void Set(string propertyName, object newValue)
public void SetNonString(string propertyName, object newValue)
{
// set cache
objectCache[propertyName] = newValue;
@@ -83,18 +116,8 @@ namespace FileManager
private void writeFile(string propertyName, JToken newValue)
{
try
{
var str = newValue?.ToString();
var formattedValue
= str is null ? "[null]"
: string.IsNullOrEmpty(str) ? "[empty]"
: string.IsNullOrWhiteSpace(str) ? $"[whitespace. Length={str.Length}]"
: str.Length > 100 ? $"[Length={str.Length}] {str[0..50]}...{str[^50..^0]}"
: str;
Serilog.Log.Logger.Information($"Config changed. {propertyName}={formattedValue}");
}
catch { }
if (IsReadOnly)
return;
// write new setting to file
lock (locker)
@@ -105,28 +128,80 @@ namespace FileManager
jObject[propertyName] = newValue;
var endContents = JsonConvert.SerializeObject(jObject, Formatting.Indented);
if (startContents != endContents)
File.WriteAllText(Filepath, endContents);
if (startContents == endContents)
return;
File.WriteAllText(Filepath, endContents);
}
try
{
var str = formatValueForLog(newValue?.ToString());
Serilog.Log.Logger.Information("Config changed. {@DebugInfo}", new { propertyName, newValue = str });
}
catch { }
}
// special case: no caching. no logging
public void SetWithJsonPath(string jsonPath, string propertyName, string newValue)
/// <summary>WILL ONLY set if already present. WILL NOT create new</summary>
/// <returns>Value was changed</returns>
public bool SetWithJsonPath(string jsonPath, string propertyName, string newValue, bool suppressLogging = false)
{
lock (locker)
{
var jObject = readFile();
var token = jObject.SelectToken(jsonPath);
var oldValue = (string)token[propertyName];
if (IsReadOnly)
return false;
if (oldValue != newValue)
var path = $"{jsonPath}.{propertyName}";
{
// only do this check in string cache, NOT object cache
if (stringCache.ContainsKey(path) && stringCache[path] == newValue)
return false;
// set cache
stringCache[path] = newValue;
}
try
{
lock (locker)
{
var jObject = readFile();
var token = jObject.SelectToken(jsonPath);
if (token is null || token[propertyName] is null)
return false;
var oldValue = token.Value<string>(propertyName);
if (oldValue == newValue)
return false;
token[propertyName] = newValue;
File.WriteAllText(Filepath, JsonConvert.SerializeObject(jObject, Formatting.Indented));
}
}
catch (Exception exDebug)
{
return false;
}
if (!suppressLogging)
{
try
{
var str = formatValueForLog(newValue?.ToString());
Serilog.Log.Logger.Information("Config changed. {@DebugInfo}", new { jsonPath, propertyName, newValue = str });
}
catch { }
}
return true;
}
private static string formatValueForLog(string value)
=> value is null ? "[null]"
: string.IsNullOrEmpty(value) ? "[empty]"
: string.IsNullOrWhiteSpace(value) ? $"[whitespace. Length={value.Length}]"
: value.Length > 100 ? $"[Length={value.Length}] {value[0..50]}...{value[^50..^0]}"
: value;
private JObject readFile()
{
var settingsJsonContents = File.ReadAllText(Filepath);

View File

@@ -13,7 +13,7 @@
<!-- <PublishSingleFile>true</PublishSingleFile> -->
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<Version>5.1.10.1</Version>
<Version>5.3.8.1</Version>
</PropertyGroup>
<ItemGroup>

View File

@@ -4,12 +4,12 @@ using System.Linq;
using System.Windows.Forms;
using AudibleApi;
using AudibleApi.Authorization;
using Dinah.Core.IO;
using Dinah.Core.Logging;
using FileManager;
using InternalUtilities;
using LibationWinForms;
using LibationWinForms.Dialogs;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Serilog;
@@ -18,209 +18,134 @@ namespace LibationLauncher
{
static class Program
{
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
static extern bool AllocConsole();
[STAThread]
static void Main()
{
//// uncomment to see Console. MUST be called before anything writes to Console. Might only work from VS
//AllocConsole();
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// must occur before access to Configuration instance
migrate_to_v5_2_0();
migrate_to_v5_2_0__pre_config();
createSettings();
//***********************************************//
// //
// do not use Configuration before this line //
// //
//***********************************************//
var config = Configuration.Instance;
createSettings(config);
AudibleApiStorage.EnsureAccountsSettingsFileExists();
migrate_to_v4_0_0();
migrate_to_v5_0_0();
ensureSerilogConfig();
configureLogging();
checkForUpdate();
logStartupState();
migrate_to_v5_0_0(config);
migrate_to_v5_2_0__post_config(config);
ensureSerilogConfig(config);
configureLogging(config);
logStartupState(config);
checkForUpdate(config);
Application.Run(new Form1());
}
private static void createSettings()
private static void createSettings(Configuration config)
{
static bool configSetupIsComplete(Configuration config)
=> config.FilesExist
&& !string.IsNullOrWhiteSpace(config.DownloadsInProgressEnum)
&& !string.IsNullOrWhiteSpace(config.DecryptInProgressEnum);
// all returns should be preceded by either:
// - if config.LibationSettingsAreValid
// - error message, Exit()
var config = Configuration.Instance;
if (configSetupIsComplete(config))
static void CancelInstallation()
{
MessageBox.Show("Initial set up cancelled.", "Cancelled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
Application.Exit();
Environment.Exit(0);
}
if (config.LibationSettingsAreValid)
return;
var isAdvanced = false;
var defaultLibationFilesDir = Configuration.UserProfile;
// check for existing settigns in default location
var defaultSettingsFile = Path.Combine(defaultLibationFilesDir, "Settings.json");
if (Configuration.SettingsFileIsValid(defaultSettingsFile))
config.SetLibationFiles(defaultLibationFilesDir);
if (config.LibationSettingsAreValid)
return;
var setupDialog = new SetupDialog();
setupDialog.NoQuestionsBtn_Click += (_, __) =>
if (setupDialog.ShowDialog() != DialogResult.OK)
{
config.DownloadsInProgressEnum ??= Configuration.WIN_TEMP_LABEL;
config.DecryptInProgressEnum ??= Configuration.WIN_TEMP_LABEL;
config.Books ??= Configuration.AppDir_Relative;
CancelInstallation();
return;
}
if (setupDialog.IsNewUser)
config.SetLibationFiles(defaultLibationFilesDir);
else if (setupDialog.IsReturningUser)
{
var libationFilesDialog = new LibationFilesDialog();
if (libationFilesDialog.ShowDialog() != DialogResult.OK)
{
CancelInstallation();
return;
}
config.SetLibationFiles(libationFilesDialog.SelectedDirectory);
if (config.LibationSettingsAreValid)
return;
// path did not result in valid settings
MessageBox.Show(
$"No valid settings were found at this location.\r\nWould you like to create a new install settings in this folder?\r\n\r\n{libationFilesDialog.SelectedDirectory}",
"New install?",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (libationFilesDialog.ShowDialog() != DialogResult.Yes)
{
CancelInstallation();
return;
}
}
// if 'new user' was clicked, or if 'returning user' chose new install: show basic settings dialog
config.Books ??= Path.Combine(defaultLibationFilesDir, "Books");
config.InProgress ??= Configuration.WinTemp;
config.AllowLibationFixup = true;
config.DecryptToLossy = false;
if (new SettingsDialog().ShowDialog() != DialogResult.OK)
{
CancelInstallation();
return;
}
if (config.LibationSettingsAreValid)
return;
CancelInstallation();
}
#region migrate_to_v5_0_0 re-register device if device info not in settings
private static void migrate_to_v5_0_0(Configuration config)
{
if (!config.Exists(nameof(config.AllowLibationFixup)))
config.AllowLibationFixup = true;
};
// setupDialog.BasicBtn_Click += (_, __) => // no action needed
setupDialog.AdvancedBtn_Click += (_, __) => isAdvanced = true;
setupDialog.ShowDialog();
if (isAdvanced)
{
var dialog = new LibationFilesDialog();
if (dialog.ShowDialog() != DialogResult.OK)
MessageBox.Show("Libation Files location not changed");
}
if (configSetupIsComplete(config))
return;
if (new SettingsDialog().ShowDialog() == DialogResult.OK)
return;
MessageBox.Show("Initial set up cancelled.", "Cancelled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
Application.Exit();
Environment.Exit(0);
}
#region v3 => v4 migration
static string AccountsSettingsFileLegacy30 => Path.Combine(Configuration.Instance.LibationFiles, "IdentityTokens.json");
private static void migrate_to_v4_0_0()
{
migrateLegacyIdentityFile();
updateSettingsFile();
}
private static void migrateLegacyIdentityFile()
{
if (File.Exists(AccountsSettingsFileLegacy30))
{
// don't always rely on applicable POCOs. some is legacy and must be: json file => JObject
try
{
updateLegacyFileWithLocale();
var account = createAccountFromLegacySettings();
account.DecryptKey = getDecryptKey(account);
// the next few methods need persistence. to be a good citizen, dispose of persister at the end of current scope
using var persister = AudibleApiStorage.GetAccountsSettingsPersister();
persister.AccountsSettings.Add(account);
}
// migration is a convenience. if something goes wrong: just move on
catch { }
// delete legacy token file
File.Delete(AccountsSettingsFileLegacy30);
}
}
private static void updateLegacyFileWithLocale()
{
var legacyContents = File.ReadAllText(AccountsSettingsFileLegacy30);
var legacyJObj = JObject.Parse(legacyContents);
// attempt to update legacy token file with locale from settings
if (!legacyJObj.ContainsKey("LocaleName"))
{
var settings = File.ReadAllText(Configuration.Instance.SettingsFilePath);
var settingsJObj = JObject.Parse(settings);
if (settingsJObj.TryGetValue("LocaleCountryCode", out var localeName))
{
// update legacy token file with locale from settings
legacyJObj.AddFirst(new JProperty("LocaleName", localeName.Value<string>()));
// save
var newContents = legacyJObj.ToString(Formatting.Indented);
File.WriteAllText(AccountsSettingsFileLegacy30, newContents);
}
}
}
private static Account createAccountFromLegacySettings()
{
// get required locale from settings file
var settingsContents = File.ReadAllText(Configuration.Instance.SettingsFilePath);
if (!JObject.Parse(settingsContents).TryGetValue("LocaleCountryCode", out var jLocale))
return null;
var localeName = jLocale.Value<string>();
var locale = Localization.Get(localeName);
var api = EzApiCreator.GetApiAsync(locale, AccountsSettingsFileLegacy30).GetAwaiter().GetResult();
var email = api.GetEmailAsync().GetAwaiter().GetResult();
// identity has likely been updated above. re-get contents
var legacyContents = File.ReadAllText(AccountsSettingsFileLegacy30);
var identity = Identity.FromJson(legacyContents);
if (!identity.IsValid)
return null;
var account = new Account(email)
{
AccountName = $"{email} - {locale.Name}",
LibraryScan = true,
IdentityTokens = identity
};
return account;
}
private static string getDecryptKey(Account account)
{
if (!string.IsNullOrWhiteSpace(account?.DecryptKey))
return account.DecryptKey;
if (!File.Exists(Configuration.Instance.SettingsFilePath) || account is null)
return "";
var settingsContents = File.ReadAllText(Configuration.Instance.SettingsFilePath);
if (JObject.Parse(settingsContents).TryGetValue("DecryptKey", out var jToken))
return jToken.Value<string>() ?? "";
return "";
}
private static void updateSettingsFile()
{
if (!File.Exists(Configuration.Instance.SettingsFilePath))
return;
// use JObject to remove decrypt key and locale from Settings.json
var settingsContents = File.ReadAllText(Configuration.Instance.SettingsFilePath);
var jObj = JObject.Parse(settingsContents);
var jLocale = jObj.Property("LocaleCountryCode");
var jDecryptKey = jObj.Property("DecryptKey");
jDecryptKey?.Remove();
jLocale?.Remove();
if (jDecryptKey != null || jLocale != null)
{
var newContents = jObj.ToString(Formatting.Indented);
File.WriteAllText(Configuration.Instance.SettingsFilePath, newContents);
}
}
#endregion
#region migrate_to_v5_0_0 re-gegister device if device info not in settings
private static void migrate_to_v5_0_0()
{
var persistentDictionary = new PersistentDictionary(Configuration.Instance.SettingsFilePath);
var config = Configuration.Instance;
if (persistentDictionary.GetString(nameof(config.AllowLibationFixup)) is null)
{
persistentDictionary.Set(nameof(config.AllowLibationFixup), true);
}
if (!File.Exists(AudibleApiStorage.AccountsSettingsFile))
return;
@@ -260,19 +185,21 @@ namespace LibationLauncher
}
#endregion
#region migrate to v5.2.0 : get rid of meta-directories, combine DownloadsInProgressEnum and DecryptInProgressEnum => InProgress
private static void migrate_to_v5_2_0()
#region migrate to v5.2.0
// get rid of meta-directories, combine DownloadsInProgressEnum and DecryptInProgressEnum => InProgress
private static void migrate_to_v5_2_0__pre_config()
{
{
var settingsKey = "DownloadsInProgressEnum";
if (UNSAFE_MigrationHelper.Settings_TryGet(settingsKey, out var value))
UNSAFE_MigrationHelper.Settings_Update(settingsKey, translatePath(value));
{
UNSAFE_MigrationHelper.Settings_Delete(settingsKey);
UNSAFE_MigrationHelper.Settings_Insert("InProgress", translatePath(value));
}
}
{
var settingsKey = "DecryptInProgressEnum";
if (UNSAFE_MigrationHelper.Settings_TryGet(settingsKey, out var value))
UNSAFE_MigrationHelper.Settings_Update(settingsKey, translatePath(value));
UNSAFE_MigrationHelper.Settings_Delete("DecryptInProgressEnum");
}
{ // appsettings.json
@@ -291,12 +218,19 @@ namespace LibationLauncher
"WinTemp" => Path.GetFullPath(Path.Combine(Path.GetTempPath(), "Libation")),
_ => path
};
private static void migrate_to_v5_2_0__post_config(Configuration config)
{
if (!config.Exists(nameof(config.AllowLibationFixup)))
config.AllowLibationFixup = true;
if (!config.Exists(nameof(config.DecryptToLossy)))
config.DecryptToLossy = false;
}
#endregion
private static void ensureSerilogConfig()
private static void ensureSerilogConfig(Configuration config)
{
var config = Configuration.Instance;
if (config.GetObject("Serilog") != null)
return;
@@ -330,7 +264,7 @@ namespace LibationLauncher
new JObject
{
// for this sink to work, a path must be provided. we override this below
{ "path", Path.Combine(Configuration.Instance.LibationFiles, "_Log.log") },
{ "path", Path.Combine(config.LibationFiles, "_Log.log") },
{ "rollingInterval", "Month" },
// Serilog template formatting examples
// - default: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
@@ -349,101 +283,26 @@ namespace LibationLauncher
config.SetObject("Serilog", serilogObj);
}
private static void configureLogging()
// to restore original: Console.SetOut(origOut);
private static TextWriter origOut { get; } = Console.Out;
private static void configureLogging(Configuration config)
{
var config = Configuration.Instance;
config.ConfigureLogging();
// override path. always use current libation files
var logPath = Path.Combine(Configuration.Instance.LibationFiles, "Log.log");
config.SetWithJsonPath("Serilog.WriteTo[1].Args", "path", logPath);
//// hack which achieves the same
//configuration["Serilog:WriteTo:1:Args:path"] = logPath;
// CONFIGURATION-DRIVEN (json)
var configuration = new ConfigurationBuilder()
.AddJsonFile(config.SettingsFilePath)
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
//// MANUAL HARD CODED
//Log.Logger = new LoggerConfiguration()
// // requires: using Dinah.Core.Logging;
// .Enrich.WithCaller()
// .MinimumLevel.Information()
// .WriteTo.File(logPath,
// rollingInterval: RollingInterval.Month,
// outputTemplate: code_outputTemplate)
// .CreateLogger();
// Fwd Console to serilog.
// Serilog also write to Console (should probably change this) so it might be asking for trouble.
// SerilogTextWriter needs to be more robust and tested. Esp the Write() methods.
// Empirical testing so far has shown no issues.
Console.SetOut(new MultiTextWriter(origOut, new SerilogTextWriter()));
// .Here() captures debug info via System.Runtime.CompilerServices attributes. Warning: expensive
//var withLineNumbers_outputTemplate = "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}in method {MemberName} at {FilePath}:{LineNumber}{NewLine}{Exception}{NewLine}";
//Log.Logger.Here().Debug("Begin Libation. Debug with line numbers");
}
private static void checkForUpdate()
private static void logStartupState(Configuration config)
{
try
{
var gitHubClient = new Octokit.GitHubClient(new Octokit.ProductHeaderValue("Libation"));
// https://octokitnet.readthedocs.io/en/latest/releases/
var releases = gitHubClient.Repository.Release.GetAll("rmcrackan", "Libation").GetAwaiter().GetResult();
var latest = releases.First(r => !r.Draft && !r.Prerelease);
var latestVersionString = latest.TagName.Trim('v');
if (!Version.TryParse(latestVersionString, out var latestRelease))
return;
// we're up to date
if (latestRelease <= BuildVersion)
return;
// we have an update
var zip = latest.Assets.FirstOrDefault(a => a.BrowserDownloadUrl.EndsWith(".zip"));
var zipUrl = zip?.BrowserDownloadUrl;
if (zipUrl is null)
{
MessageBox.Show(latest.HtmlUrl, "New version available");
return;
}
var result = MessageBox.Show($"New version available @ {latest.HtmlUrl}\r\nDownload the zip file?", "New version available", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
if (result != DialogResult.Yes)
return;
using var fileSelector = new SaveFileDialog { FileName = zip.Name, Filter = "Zip Files (*.zip)|*.zip|All files (*.*)|*.*" };
if (fileSelector.ShowDialog() != DialogResult.OK)
return;
var selectedPath = fileSelector.FileName;
try
{
LibationWinForms.BookLiberation.ProcessorAutomationController.DownloadFile(zipUrl, selectedPath, true);
}
catch (Exception ex)
{
Error(ex, "Error downloading update");
}
}
catch (Exception ex)
{
Error(ex, "Error checking for update");
}
}
private static void Error(Exception ex, string message)
{
Log.Logger.Error(ex, message);
MessageBox.Show($"{message}\r\nSee log for details");
}
private static void logStartupState()
{
var config = Configuration.Instance;
// begin logging session with a form feed
Log.Logger.Information("\r\n\f");
Log.Logger.Information("Begin Libation. {@DebugInfo}", new
@@ -460,28 +319,101 @@ namespace LibationLauncher
config.LibationFiles,
AudibleFileStorage.BooksDirectory,
config.DownloadsInProgressEnum,
config.InProgress,
DownloadsInProgressDir = AudibleFileStorage.DownloadsInProgress,
DownloadsInProgressFiles = Directory.EnumerateFiles(AudibleFileStorage.DownloadsInProgress).Count(),
config.DecryptInProgressEnum,
DecryptInProgressDir = AudibleFileStorage.DecryptInProgress,
DecryptInProgressFiles = Directory.EnumerateFiles(AudibleFileStorage.DecryptInProgress).Count(),
});
// when turning on debug (and especially Verbose) to share logs, some privacy settings may not be obscured
if (Log.Logger.IsVerboseEnabled())
MessageBox.Show(@"
Warning: verbose logging is enabled.
MessageBoxVerboseLoggingWarning.ShowIfTrue();
}
This should be used for debugging only. It creates many
more logs and debug files, neither of which are as
strictly anonomous.
private static void checkForUpdate(Configuration config)
{
string zipUrl;
string selectedPath;
When you are finished debugging, it's highly recommended
to set your debug MinimumLevel to Information and restart
Libation.
".Trim(), "Verbose logging enabled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
try
{
// timed out
var latest = getLatestRelease(TimeSpan.FromSeconds(10));
if (latest is null)
return;
var latestVersionString = latest.TagName.Trim('v');
if (!Version.TryParse(latestVersionString, out var latestRelease))
return;
// we're up to date
if (latestRelease <= BuildVersion)
return;
// we have an update
var zip = latest.Assets.FirstOrDefault(a => a.BrowserDownloadUrl.EndsWith(".zip"));
zipUrl = zip?.BrowserDownloadUrl;
Log.Logger.Information("Update available: {@DebugInfo}", new {
latestRelease = latestRelease.ToString(),
latest.HtmlUrl,
zipUrl
});
if (zipUrl is null)
{
MessageBox.Show(latest.HtmlUrl, "New version available");
return;
}
var result = MessageBox.Show($"New version available @ {latest.HtmlUrl}\r\nDownload the zip file?", "New version available", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result != DialogResult.Yes)
return;
using var fileSelector = new SaveFileDialog { FileName = zip.Name, Filter = "Zip Files (*.zip)|*.zip|All files (*.*)|*.*" };
if (fileSelector.ShowDialog() != DialogResult.OK)
return;
selectedPath = fileSelector.FileName;
}
catch (AggregateException aggEx)
{
Log.Logger.Error(aggEx, "Checking for new version too often");
return;
}
catch (Exception ex)
{
MessageBoxAlertAdmin.Show("Error checking for update", "Error checking for update", ex);
return;
}
try
{
LibationWinForms.BookLiberation.ProcessorAutomationController.DownloadFile(zipUrl, selectedPath, true);
}
catch (Exception ex)
{
MessageBoxAlertAdmin.Show("Error downloading update", "Error downloading update", ex);
}
}
private static Octokit.Release getLatestRelease(TimeSpan timeout)
{
var task = System.Threading.Tasks.Task.Run(() => getLatestRelease());
if (task.Wait(timeout))
return task.Result;
Log.Logger.Information("Timed out");
return null;
}
private static Octokit.Release getLatestRelease()
{
var gitHubClient = new Octokit.GitHubClient(new Octokit.ProductHeaderValue("Libation"));
// https://octokitnet.readthedocs.io/en/latest/releases/
var releases = gitHubClient.Repository.Release.GetAll("rmcrackan", "Libation").GetAwaiter().GetResult();
var latest = releases.First(r => !r.Draft && !r.Prerelease);
return latest;
}
private static Version BuildVersion => System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;

View File

@@ -31,7 +31,6 @@
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.bookInfoLbl = new System.Windows.Forms.Label();
this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.rtbLog = new System.Windows.Forms.RichTextBox();
this.remainingTimeLbl = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
@@ -60,28 +59,16 @@
//
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(14, 607);
this.progressBar1.Location = new System.Drawing.Point(14, 143);
this.progressBar1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(611, 27);
this.progressBar1.TabIndex = 2;
//
// rtbLog
//
this.rtbLog.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.rtbLog.Location = new System.Drawing.Point(14, 136);
this.rtbLog.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.rtbLog.Name = "rtbLog";
this.rtbLog.Size = new System.Drawing.Size(678, 463);
this.rtbLog.TabIndex = 1;
this.rtbLog.Text = "";
//
// remainingTimeLbl
//
this.remainingTimeLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.remainingTimeLbl.Location = new System.Drawing.Point(632, 607);
this.remainingTimeLbl.Location = new System.Drawing.Point(632, 143);
this.remainingTimeLbl.Name = "remainingTimeLbl";
this.remainingTimeLbl.Size = new System.Drawing.Size(60, 31);
this.remainingTimeLbl.TabIndex = 3;
@@ -92,9 +79,8 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(707, 647);
this.ClientSize = new System.Drawing.Size(707, 183);
this.Controls.Add(this.remainingTimeLbl);
this.Controls.Add(this.rtbLog);
this.Controls.Add(this.progressBar1);
this.Controls.Add(this.bookInfoLbl);
this.Controls.Add(this.pictureBox1);
@@ -102,8 +88,6 @@
this.Name = "DecryptForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "DecryptForm";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DecryptForm_FormClosing);
this.Load += new System.EventHandler(this.DecryptForm_Load);
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
@@ -115,7 +99,6 @@
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Label bookInfoLbl;
private System.Windows.Forms.ProgressBar progressBar1;
private System.Windows.Forms.RichTextBox rtbLog;
private System.Windows.Forms.Label remainingTimeLbl;
}
}

View File

@@ -1,43 +1,21 @@
using System;
using System.Windows.Forms;
using Dinah.Core.Drawing;
using Dinah.Core.IO;
using Dinah.Core.Windows.Forms;
namespace LibationWinForms.BookLiberation
{
public partial class DecryptForm : Form
{
public DecryptForm()
{
InitializeComponent();
}
System.IO.TextWriter origOut { get; } = Console.Out;
private void DecryptForm_Load(object sender, EventArgs e)
{
// redirect Console.WriteLine to console, textbox
var multiLogger = new MultiTextWriter(
origOut,
new RichTextBoxTextWriter(this.rtbLog),
new SerilogTextWriter());
Console.SetOut(multiLogger);
}
private void DecryptForm_FormClosing(object sender, FormClosingEventArgs e)
{
// restore original
Console.SetOut(origOut);
}
public DecryptForm() => InitializeComponent();
// book info
string title;
string authorNames;
string narratorNames;
private string title;
private string authorNames;
private string narratorNames;
public void SetTitle(string title)
{
this.UIThread(() => this.Text = " Decrypting " + title);
this.UIThread(() => this.Text = "Decrypting " + title);
this.title = title;
updateBookInfo();
}
@@ -62,15 +40,15 @@ namespace LibationWinForms.BookLiberation
public void UpdateProgress(int percentage)
{
if (percentage == 0)
remainingTimeLbl.UIThread(() => remainingTimeLbl.Text = "ETA:\r\n0 sec");
updateRemainingTime(0);
else
progressBar1.UIThread(() => progressBar1.Value = percentage);
}
public void UpdateRemainingTime(TimeSpan remaining)
{
remainingTimeLbl.UIThread(() => remainingTimeLbl.Text = $"ETA:\r\n{(int)remaining.TotalSeconds} sec");
}
=> updateRemainingTime((int)remaining.TotalSeconds);
private void updateRemainingTime(int remaining)
=> remainingTimeLbl.UIThread(() => remainingTimeLbl.Text = $"ETA:\r\n{remaining} sec");
}
}

View File

@@ -3,6 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using DataLayer;
using Dinah.Core;
using Dinah.Core.ErrorHandling;
using Dinah.Core.Windows.Forms;
using FileLiberator;
@@ -440,7 +441,26 @@ namespace LibationWinForms.BookLiberation
LogMe.Error("ERROR. All books have not been processed. Most recent book: processing failed");
var dialogResult = MessageBox.Show(SkipDialogText, "Skip importing this book?", SkipDialogButtons, MessageBoxIcon.Question);
string details;
try
{
static string trunc(string str)
=> string.IsNullOrWhiteSpace(str) ? "[empty]"
: (str.Length > 50) ? $"{str.Truncate(47)}..."
: str;
details =
$@" Title: {libraryBook.Book.Title}
ID: {libraryBook.Book.AudibleProductId}
Author: {trunc(libraryBook.Book.AuthorNames)}
Narr: {trunc(libraryBook.Book.NarratorNames)}";
}
catch
{
details = "[Error retrieving details]";
}
var dialogResult = MessageBox.Show(string.Format(SkipDialogText, details), "Skip importing this book?", SkipDialogButtons, MessageBoxIcon.Question);
if (dialogResult == DialogResult.Abort)
return false;
@@ -464,6 +484,7 @@ Created new 'skip' file
protected override string SkipDialogText => @"
An error occurred while trying to process this book. Skip this book permanently?
{0}
- Click YES to skip this book permanently.
@@ -487,7 +508,8 @@ An error occurred while trying to process this book. Skip this book permanently?
class BackupLoop : BackupRunner
{
protected override string SkipDialogText => @"
An error occurred while trying to process this book
An error occurred while trying to process this book.
{0}
- ABORT: stop processing books.

View File

@@ -125,7 +125,7 @@ namespace LibationWinForms.Dialogs
}
catch (Exception ex)
{
MessageBox.Show($"Error: {ex.Message}", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
MessageBoxAlertAdmin.Show("Error attempting to save accounts", "Error saving accounts", ex);
}
}

View File

@@ -49,7 +49,7 @@ namespace LibationWinForms.Dialogs
// customDirectoryRb
//
this.customDirectoryRb.AutoSize = true;
this.customDirectoryRb.Location = new System.Drawing.Point(2, 56);
this.customDirectoryRb.Location = new System.Drawing.Point(2, 62);
this.customDirectoryRb.Name = "customDirectoryRb";
this.customDirectoryRb.Size = new System.Drawing.Size(14, 13);
this.customDirectoryRb.TabIndex = 2;
@@ -60,7 +60,7 @@ namespace LibationWinForms.Dialogs
//
this.customTb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.customTb.Location = new System.Drawing.Point(22, 52);
this.customTb.Location = new System.Drawing.Point(22, 58);
this.customTb.Name = "customTb";
this.customTb.Size = new System.Drawing.Size(588, 23);
this.customTb.TabIndex = 3;
@@ -68,7 +68,7 @@ namespace LibationWinForms.Dialogs
// customBtn
//
this.customBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.customBtn.Location = new System.Drawing.Point(616, 52);
this.customBtn.Location = new System.Drawing.Point(616, 58);
this.customBtn.Name = "customBtn";
this.customBtn.Size = new System.Drawing.Size(41, 27);
this.customBtn.TabIndex = 4;
@@ -82,7 +82,7 @@ namespace LibationWinForms.Dialogs
| System.Windows.Forms.AnchorStyles.Right)));
this.directorySelectControl.Location = new System.Drawing.Point(23, 0);
this.directorySelectControl.Name = "directorySelectControl";
this.directorySelectControl.Size = new System.Drawing.Size(635, 46);
this.directorySelectControl.Size = new System.Drawing.Size(635, 52);
this.directorySelectControl.TabIndex = 5;
//
// DirectoryOrCustomSelectControl
@@ -95,7 +95,7 @@ namespace LibationWinForms.Dialogs
this.Controls.Add(this.customDirectoryRb);
this.Controls.Add(this.knownDirectoryRb);
this.Name = "DirectoryOrCustomSelectControl";
this.Size = new System.Drawing.Size(660, 81);
this.Size = new System.Drawing.Size(660, 87);
this.Load += new System.EventHandler(this.DirectoryOrCustomSelectControl_Load);
this.ResumeLayout(false);
this.PerformLayout();

View File

@@ -9,9 +9,11 @@ namespace LibationWinForms.Dialogs
{
public partial class DirectoryOrCustomSelectControl : UserControl
{
public bool SelectedDirectoryIsKnown => knownDirectoryRb.Checked;
public bool SelectedDirectoryIsCustom => customDirectoryRb.Checked;
public string SelectedDirectory
=> customDirectoryRb.Checked ? customTb.Text.Trim()
: knownDirectoryRb.Checked ? directorySelectControl.SelectedDirectory
=> SelectedDirectoryIsKnown ? directorySelectControl.SelectedDirectory
: SelectedDirectoryIsCustom ? customTb.Text.Trim()
: null;
public DirectoryOrCustomSelectControl()
@@ -25,8 +27,8 @@ namespace LibationWinForms.Dialogs
/// <summary>Set items for combobox</summary>
/// <param name="knownDirectories">List rather than IEnumerable so that client can determine display order</param>
/// <param name="defaultDirectory"></param>
public void SetDirectoryItems(List<Configuration.KnownDirectories> knownDirectories, Configuration.KnownDirectories? defaultDirectory = Configuration.KnownDirectories.UserProfile)
=> this.directorySelectControl.SetDirectoryItems(knownDirectories, defaultDirectory);
public void SetDirectoryItems(List<Configuration.KnownDirectories> knownDirectories, Configuration.KnownDirectories? defaultDirectory = Configuration.KnownDirectories.UserProfile, string subDirectory = null)
=> this.directorySelectControl.SetDirectoryItems(knownDirectories, defaultDirectory, subDirectory);
/// <summary>set selection</summary>
/// <param name="directory"></param>
@@ -41,7 +43,13 @@ namespace LibationWinForms.Dialogs
public void SelectDirectory(string directory)
{
directory = directory?.Trim() ?? "";
selectDir(Configuration.GetKnownDirectory(directory), directory);
// remove SubDirectory setting to find known directories
var noSubDir = this.directorySelectControl.RemoveSubDirectoryFromPath(directory);
var knownDir = Configuration.GetKnownDirectory(noSubDir);
// DO NOT remove SubDirectory setting for custom
var customDir = directory;
selectDir(knownDir, customDir);
}
private void selectDir(Configuration.KnownDirectories knownDir, string customDir)

View File

@@ -30,7 +30,7 @@ namespace LibationWinForms.Dialogs
private void InitializeComponent()
{
this.directoryComboBox = new System.Windows.Forms.ComboBox();
this.label1 = new System.Windows.Forms.Label();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// directoryComboBox
@@ -45,23 +45,24 @@ namespace LibationWinForms.Dialogs
this.directoryComboBox.TabIndex = 0;
this.directoryComboBox.SelectedIndexChanged += new System.EventHandler(this.directoryComboBox_SelectedIndexChanged);
//
// label1
// textBox1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(0, 26);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(97, 15);
this.label1.TabIndex = 1;
this.label1.Text = "Select a directory";
this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBox1.Location = new System.Drawing.Point(0, 29);
this.textBox1.Name = "textBox1";
this.textBox1.ReadOnly = true;
this.textBox1.Size = new System.Drawing.Size(647, 23);
this.textBox1.TabIndex = 1;
//
// DirectorySelectControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.label1);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.directoryComboBox);
this.Name = "DirectorySelectControl";
this.Size = new System.Drawing.Size(647, 46);
this.Size = new System.Drawing.Size(647, 52);
this.Load += new System.EventHandler(this.DirectorySelectControl_Load);
this.ResumeLayout(false);
this.PerformLayout();
@@ -71,6 +72,6 @@ namespace LibationWinForms.Dialogs
#endregion
private System.Windows.Forms.ComboBox directoryComboBox;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox1;
}
}

View File

@@ -13,14 +13,17 @@ namespace LibationWinForms.Dialogs
{
public string Description { get; }
public Configuration.KnownDirectories Value { get; }
private DirectorySelectControl _parentControl;
public string FullPath => Configuration.GetKnownDirectoryPath(Value);
public string FullPath => _parentControl.AddSubDirectoryToPath(Configuration.GetKnownDirectoryPath(Value));
/// <summary>Displaying relative paths is confusing. UI should display absolute equivalent</summary>
public string UiDisplayPath => Value == Configuration.KnownDirectories.AppDir ? Configuration.AppDir_Absolute : FullPath;
public string UiDisplayPath => Value == Configuration.KnownDirectories.AppDir ? _parentControl.AddSubDirectoryToPath(Configuration.AppDir_Absolute) : FullPath;
public DirectoryComboBoxItem(Configuration.KnownDirectories knownDirectory)
public DirectoryComboBoxItem(DirectorySelectControl parentControl, Configuration.KnownDirectories knownDirectory)
{
_parentControl = parentControl;
Value = knownDirectory;
Description = Value.GetDescription();
}
@@ -28,20 +31,42 @@ namespace LibationWinForms.Dialogs
public override string ToString() => Description;
}
private DirectoryComboBoxItem selectedItem => (DirectoryComboBoxItem)this.directoryComboBox.SelectedItem;
public string SelectedDirectory => selectedItem?.FullPath;
private string _subDirectory;
internal string AddSubDirectoryToPath(string path) => string.IsNullOrWhiteSpace(_subDirectory) ? path : System.IO.Path.Combine(path, _subDirectory);
internal string RemoveSubDirectoryFromPath(string path)
{
if (string.IsNullOrWhiteSpace(_subDirectory))
return path;
path = path?.Trim() ?? "";
if (string.IsNullOrWhiteSpace(path))
return path;
var bottomDir = System.IO.Path.GetFileName(path);
if (_subDirectory.EqualsInsensitive(bottomDir))
return System.IO.Path.GetDirectoryName(path);
return path;
}
private DirectoryComboBoxItem selectedItem => (DirectoryComboBoxItem)this.directoryComboBox.SelectedItem;
public DirectorySelectControl() => InitializeComponent();
/// <summary>Set items for combobox</summary>
/// <param name="knownDirectories">List rather than IEnumerable so that client can determine display order</param>
/// <param name="defaultDirectory">Optional default item to select</param>
public void SetDirectoryItems(List<Configuration.KnownDirectories> knownDirectories, Configuration.KnownDirectories? defaultDirectory = null)
public void SetDirectoryItems(List<Configuration.KnownDirectories> knownDirectories, Configuration.KnownDirectories? defaultDirectory = null, string subDirectory = null)
{
// set this 1st so all DirectoryComboBoxItems can reference it
_subDirectory = subDirectory;
this.directoryComboBox.Items.Clear();
foreach (var dir in knownDirectories.Where(d => d != Configuration.KnownDirectories.None).Distinct())
this.directoryComboBox.Items.Add(new DirectoryComboBoxItem(dir));
this.directoryComboBox.Items.Add(new DirectoryComboBoxItem(this, dir));
SelectDirectory(defaultDirectory);
}
@@ -49,7 +74,14 @@ namespace LibationWinForms.Dialogs
/// <summary>set selection</summary>
/// <param name="directory"></param>
/// <returns>True is there was a matching entry</returns>
public bool SelectDirectory(string directory) => SelectDirectory(Configuration.GetKnownDirectory(directory));
public bool SelectDirectory(string directory)
{
directory = directory?.Trim() ?? "";
var noSubDir = RemoveSubDirectoryFromPath(directory);
var knownDir = Configuration.GetKnownDirectory(noSubDir);
return SelectDirectory(knownDir);
}
/// <summary>set selection</summary>
/// <param name="directory"></param>
@@ -75,6 +107,6 @@ namespace LibationWinForms.Dialogs
}
private void directoryComboBox_SelectedIndexChanged(object sender, EventArgs e) => this.label1.Text = selectedItem.UiDisplayPath;
private void directoryComboBox_SelectedIndexChanged(object sender, EventArgs e) => this.textBox1.Text = selectedItem.UiDisplayPath;
}
}

View File

@@ -35,9 +35,10 @@ namespace LibationWinForms.Dialogs
}
catch (Exception ex)
{
var msg = "Error importing library. Please try again. If this still happens after 2 or 3 tries, stop and contact administrator";
Serilog.Log.Logger.Error(ex, msg);
MessageBox.Show(msg, "Error importing library", MessageBoxButtons.OK, MessageBoxIcon.Error);
MessageBoxAlertAdmin.Show(
"Error importing library. Please try again. If this still happens after 2 or 3 tries, stop and contact administrator",
"Error importing library",
ex);
}
}

View File

@@ -31,7 +31,7 @@
this.libationFilesDescLbl = new System.Windows.Forms.Label();
this.cancelBtn = new System.Windows.Forms.Button();
this.saveBtn = new System.Windows.Forms.Button();
this.directoryOrCustomSelectControl = new LibationWinForms.Dialogs.DirectoryOrCustomSelectControl();
this.libationFilesSelectControl = new LibationWinForms.Dialogs.DirectoryOrCustomSelectControl();
this.SuspendLayout();
//
// libationFilesDescLbl
@@ -52,7 +52,7 @@
this.cancelBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.cancelBtn.Name = "cancelBtn";
this.cancelBtn.Size = new System.Drawing.Size(88, 27);
this.cancelBtn.TabIndex = 10;
this.cancelBtn.TabIndex = 3;
this.cancelBtn.Text = "Cancel";
this.cancelBtn.UseVisualStyleBackColor = true;
this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click);
@@ -64,26 +64,26 @@
this.saveBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.saveBtn.Name = "saveBtn";
this.saveBtn.Size = new System.Drawing.Size(88, 27);
this.saveBtn.TabIndex = 9;
this.saveBtn.TabIndex = 2;
this.saveBtn.Text = "Save";
this.saveBtn.UseVisualStyleBackColor = true;
this.saveBtn.Click += new System.EventHandler(this.saveBtn_Click);
//
// directoryOrCustomSelectControl
// libationFilesSelectControl
//
this.directoryOrCustomSelectControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
this.libationFilesSelectControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.directoryOrCustomSelectControl.Location = new System.Drawing.Point(14, 28);
this.directoryOrCustomSelectControl.Name = "directoryOrCustomSelectControl";
this.directoryOrCustomSelectControl.Size = new System.Drawing.Size(909, 81);
this.directoryOrCustomSelectControl.TabIndex = 11;
this.libationFilesSelectControl.Location = new System.Drawing.Point(14, 28);
this.libationFilesSelectControl.Name = "libationFilesSelectControl";
this.libationFilesSelectControl.Size = new System.Drawing.Size(909, 87);
this.libationFilesSelectControl.TabIndex = 1;
//
// LibationFilesDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(933, 158);
this.Controls.Add(this.directoryOrCustomSelectControl);
this.ClientSize = new System.Drawing.Size(933, 164);
this.Controls.Add(this.libationFilesSelectControl);
this.Controls.Add(this.cancelBtn);
this.Controls.Add(this.saveBtn);
this.Controls.Add(this.libationFilesDescLbl);
@@ -103,6 +103,6 @@
private System.Windows.Forms.Label libationFilesDescLbl;
private System.Windows.Forms.Button cancelBtn;
private System.Windows.Forms.Button saveBtn;
private DirectoryOrCustomSelectControl directoryOrCustomSelectControl;
private DirectoryOrCustomSelectControl libationFilesSelectControl;
}
}

View File

@@ -6,8 +6,7 @@ namespace LibationWinForms.Dialogs
{
public partial class LibationFilesDialog : Form
{
private Configuration config { get; } = Configuration.Instance;
private Func<string, string> desc { get; } = Configuration.GetDescription;
public string SelectedDirectory { get; private set; }
public LibationFilesDialog() => InitializeComponent();
@@ -16,27 +15,32 @@ namespace LibationWinForms.Dialogs
if (this.DesignMode)
return;
libationFilesDescLbl.Text = desc(nameof(config.LibationFiles));
var config = Configuration.Instance;
directoryOrCustomSelectControl.SetSearchTitle("Libation Files");
directoryOrCustomSelectControl.SetDirectoryItems(new()
libationFilesDescLbl.Text = Configuration.GetDescription(nameof(config.LibationFiles));
libationFilesSelectControl.SetSearchTitle("Libation Files");
libationFilesSelectControl.SetDirectoryItems(new()
{
Configuration.KnownDirectories.UserProfile,
Configuration.KnownDirectories.AppDir,
Configuration.KnownDirectories.MyDocs
}, Configuration.KnownDirectories.UserProfile);
directoryOrCustomSelectControl.SelectDirectory(config.LibationFiles);
libationFilesSelectControl.SelectDirectory(config.LibationFiles);
}
private void saveBtn_Click(object sender, EventArgs e)
{
var libationDir = directoryOrCustomSelectControl.SelectedDirectory;
if (!config.TrySetLibationFiles(libationDir))
var libationDir = libationFilesSelectControl.SelectedDirectory;
if (!System.IO.Directory.Exists(libationDir))
{
MessageBox.Show("Not saving change to Libation Files location. This folder does not exist:\r\n" + libationDir);
MessageBox.Show("Not saving change to Libation Files location. This folder does not exist:\r\n" + libationDir, "Folder does not exist", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
SelectedDirectory = libationDir;
this.DialogResult = DialogResult.OK;
this.Close();
}

View File

@@ -14,49 +14,74 @@ namespace LibationWinForms.Dialogs.Login
{
private RadioButton[] radioButtons { get; }
AudibleApi.MfaConfig _mfaConfig { get; }
public MfaDialog(AudibleApi.MfaConfig mfaConfig)
{
InitializeComponent();
_mfaConfig = mfaConfig;
radioButtons = new[] { this.radioButton1, this.radioButton2, this.radioButton3 };
// optional string settings
if (!string.IsNullOrWhiteSpace(mfaConfig.Title))
this.Text = mfaConfig.Title;
setOptional(this.radioButton1, mfaConfig.Button1Text);
setOptional(this.radioButton2, mfaConfig.Button2Text);
setOptional(this.radioButton3, mfaConfig.Button3Text);
// mandatory values
radioButton1.Name = mfaConfig.Button1Name;
radioButton1.Tag = mfaConfig.Button1Value;
setRadioButton(0, this.radioButton1);
setRadioButton(1, this.radioButton2);
setRadioButton(2, this.radioButton3);
radioButton2.Name = mfaConfig.Button2Name;
radioButton2.Tag = mfaConfig.Button2Value;
radioButton3.Name = mfaConfig.Button3Name;
radioButton3.Tag = mfaConfig.Button3Value;
Serilog.Log.Logger.Information("{@DebugInfo}", new {
paramButtonCount = mfaConfig.Buttons.Count,
visibleRadioButtonCount = radioButtons.Count(rb => rb.Visible)
});
}
private static void setOptional(RadioButton radioButton, string text)
private void setRadioButton(int pos, RadioButton rb)
{
if (!string.IsNullOrWhiteSpace(text))
radioButton.Text = text;
if (_mfaConfig.Buttons.Count <= pos)
{
rb.Checked = false;
rb.Enabled = false;
rb.Visible = false;
return;
}
var btn = _mfaConfig.Buttons[pos];
// optional
if (!string.IsNullOrWhiteSpace(btn.Text))
rb.Text = btn.Text;
// mandatory values
rb.Name = btn.Name;
rb.Tag = btn.Value;
}
public string SelectedName { get; private set; }
public string SelectedValue { get; private set; }
private void submitBtn_Click(object sender, EventArgs e)
{
Serilog.Log.Logger.Debug("RadioButton states: {@DebugInfo}", new {
Serilog.Log.Logger.Information("RadioButton states: {@DebugInfo}", new {
rb1_visible = radioButton1.Visible,
rb1_checked = radioButton1.Checked,
r21_visible = radioButton2.Visible,
r21_checked = radioButton2.Checked,
rb3_visible = radioButton3.Visible,
rb3_checked = radioButton3.Checked
});
var selected = radioButtons.Single(rb => rb.Checked);
var selected = radioButtons.FirstOrDefault(rb => rb.Checked);
if (selected is null)
{
MessageBox.Show("No MFA option selected", "None selected", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Serilog.Log.Logger.Debug("Selected: {@DebugInfo}", new { isSelected = selected is not null, name = selected?.Name, value = selected?.Tag });
Serilog.Log.Logger.Information("Selected: {@DebugInfo}", new { isSelected = selected is not null, name = selected?.Name, value = selected?.Tag });
SelectedName = selected.Name;
SelectedValue = (string)selected.Tag;

View File

@@ -17,7 +17,7 @@ namespace LibationWinForms.Login
public string Get2faCode()
{
using var dialog = new _2faCodeDialog();
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
if (showDialog(dialog))
return dialog.Code;
return null;
}
@@ -25,7 +25,7 @@ namespace LibationWinForms.Login
public string GetCaptchaAnswer(byte[] captchaImage)
{
using var dialog = new CaptchaDialog(captchaImage);
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
if (showDialog(dialog))
return dialog.Answer;
return null;
}
@@ -33,7 +33,7 @@ namespace LibationWinForms.Login
public (string name, string value) GetMfaChoice(MfaConfig mfaConfig)
{
using var dialog = new MfaDialog(mfaConfig);
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
if (showDialog(dialog))
return (dialog.SelectedName, dialog.SelectedValue);
return (null, null);
}
@@ -41,7 +41,7 @@ namespace LibationWinForms.Login
public (string email, string password) GetLogin()
{
using var dialog = new AudibleLoginDialog(_account);
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
if (showDialog(dialog))
return (dialog.Email, dialog.Password);
return (null, null);
}
@@ -49,7 +49,15 @@ namespace LibationWinForms.Login
public void ShowApprovalNeeded()
{
using var dialog = new ApprovalNeededDialog();
dialog.ShowDialog();
showDialog(dialog);
}
/// <returns>True if ShowDialog's DialogResult == OK</returns>
private static bool showDialog(System.Windows.Forms.Form dialog)
{
var result = dialog.ShowDialog();
Serilog.Log.Logger.Debug("{@DebugInfo}", new { DialogResult = result });
return result == System.Windows.Forms.DialogResult.OK;
}
}
}

View File

@@ -0,0 +1,155 @@

namespace LibationWinForms.Dialogs
{
partial class MessageBoxAlertAdminDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MessageBoxAlertAdminDialog));
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.descriptionLbl = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.githubLink = new System.Windows.Forms.LinkLabel();
this.okBtn = new System.Windows.Forms.Button();
this.logsLink = new System.Windows.Forms.LinkLabel();
this.exceptionTb = new System.Windows.Forms.TextBox();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.Location = new System.Drawing.Point(12, 12);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(64, 64);
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
//
// descriptionLbl
//
this.descriptionLbl.AutoSize = true;
this.descriptionLbl.Location = new System.Drawing.Point(82, 12);
this.descriptionLbl.Name = "descriptionLbl";
this.descriptionLbl.Size = new System.Drawing.Size(89, 45);
this.descriptionLbl.TabIndex = 0;
this.descriptionLbl.Text = "[Error message]\r\n[Error message]\r\n[Error message]";
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 244);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(269, 90);
this.label1.TabIndex = 2;
this.label1.Text = resources.GetString("label1.Text");
//
// githubLink
//
this.githubLink.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.githubLink.AutoSize = true;
this.githubLink.Location = new System.Drawing.Point(271, 274);
this.githubLink.Name = "githubLink";
this.githubLink.Size = new System.Drawing.Size(116, 15);
this.githubLink.TabIndex = 3;
this.githubLink.TabStop = true;
this.githubLink.Text = "Click to go to github";
this.githubLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.githubLink_LinkClicked);
//
// okBtn
//
this.okBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.okBtn.Location = new System.Drawing.Point(256, 347);
this.okBtn.Name = "okBtn";
this.okBtn.Size = new System.Drawing.Size(75, 23);
this.okBtn.TabIndex = 5;
this.okBtn.Text = "OK";
this.okBtn.UseVisualStyleBackColor = true;
this.okBtn.Click += new System.EventHandler(this.okBtn_Click);
//
// logsLink
//
this.logsLink.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.logsLink.AutoSize = true;
this.logsLink.Location = new System.Drawing.Point(271, 289);
this.logsLink.Name = "logsLink";
this.logsLink.Size = new System.Drawing.Size(155, 15);
this.logsLink.TabIndex = 4;
this.logsLink.TabStop = true;
this.logsLink.Text = "Click to open log files folder";
this.logsLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.logsLink_LinkClicked);
//
// exceptionTb
//
this.exceptionTb.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.exceptionTb.Location = new System.Drawing.Point(12, 82);
this.exceptionTb.Multiline = true;
this.exceptionTb.Name = "exceptionTb";
this.exceptionTb.ReadOnly = true;
this.exceptionTb.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.exceptionTb.Size = new System.Drawing.Size(560, 159);
this.exceptionTb.TabIndex = 1;
//
// MessageBoxAlertAdminDialog
//
this.AcceptButton = this.okBtn;
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(584, 382);
this.Controls.Add(this.exceptionTb);
this.Controls.Add(this.logsLink);
this.Controls.Add(this.okBtn);
this.Controls.Add(this.githubLink);
this.Controls.Add(this.label1);
this.Controls.Add(this.descriptionLbl);
this.Controls.Add(this.pictureBox1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "MessageBoxAlertAdminDialog";
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "MessageBoxAlertAdmin";
this.Load += new System.EventHandler(this.MessageBoxAlertAdminDialog_Load);
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Label descriptionLbl;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.LinkLabel githubLink;
private System.Windows.Forms.Button okBtn;
private System.Windows.Forms.LinkLabel logsLink;
private System.Windows.Forms.TextBox exceptionTb;
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using Dinah.Core;
namespace LibationWinForms.Dialogs
{
public partial class MessageBoxAlertAdminDialog : Form
{
public MessageBoxAlertAdminDialog() => InitializeComponent();
/// <summary>
/// Displays a message box with specified text and caption.
/// </summary>
/// <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 display</param>
public MessageBoxAlertAdminDialog(string text, string caption, Exception exception) : this()
{
this.descriptionLbl.Text = text;
this.Text = caption;
this.exceptionTb.Text = $"{exception.Message}\r\n\r\n{exception.StackTrace}";
}
private void MessageBoxAlertAdminDialog_Load(object sender, EventArgs e)
{
if (this.DesignMode)
return;
System.Media.SystemSounds.Hand.Play();
pictureBox1.Image = SystemIcons.Error.ToBitmap();
}
private void githubLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
=> Go.To.Url("https://github.com/rmcrackan/Libation/issues");
private void logsLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
=> Go.To.Folder(FileManager.Configuration.Instance.LibationFiles);
private void okBtn_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
this.Close();
}
}
}

View File

@@ -57,4 +57,12 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="label1.Text" xml:space="preserve">
<value>If you'd like to report this error to an advinistrator:
Step 1: Go to Libation's "issues" page on github
Step 2: Find your log files
Setp 3: Click "New issue" button
Step 4: Drag/drop your log files</value>
</data>
</root>

View File

@@ -28,174 +28,52 @@
/// </summary>
private void InitializeComponent()
{
this.booksLocationLbl = new System.Windows.Forms.Label();
this.booksLocationTb = new System.Windows.Forms.TextBox();
this.booksLocationSearchBtn = new System.Windows.Forms.Button();
this.booksLocationDescLbl = new System.Windows.Forms.Label();
this.downloadsInProgressGb = new System.Windows.Forms.GroupBox();
this.downloadsInProgressLibationFilesRb = new System.Windows.Forms.RadioButton();
this.downloadsInProgressWinTempRb = new System.Windows.Forms.RadioButton();
this.downloadsInProgressDescLbl = new System.Windows.Forms.Label();
this.decryptInProgressGb = new System.Windows.Forms.GroupBox();
this.decryptInProgressLibationFilesRb = new System.Windows.Forms.RadioButton();
this.decryptInProgressWinTempRb = new System.Windows.Forms.RadioButton();
this.decryptInProgressDescLbl = new System.Windows.Forms.Label();
this.inProgressDescLbl = new System.Windows.Forms.Label();
this.saveBtn = new System.Windows.Forms.Button();
this.cancelBtn = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.advancedSettingsGb = new System.Windows.Forms.GroupBox();
this.convertLossyRb = new System.Windows.Forms.RadioButton();
this.convertLosslessRb = new System.Windows.Forms.RadioButton();
this.inProgressSelectControl = new LibationWinForms.Dialogs.DirectorySelectControl();
this.allowLibationFixupCbox = new System.Windows.Forms.CheckBox();
this.downloadsInProgressGb.SuspendLayout();
this.decryptInProgressGb.SuspendLayout();
this.groupBox1.SuspendLayout();
this.logsBtn = new System.Windows.Forms.Button();
this.booksSelectControl = new LibationWinForms.Dialogs.DirectoryOrCustomSelectControl();
this.booksGb = new System.Windows.Forms.GroupBox();
this.loggingLevelLbl = new System.Windows.Forms.Label();
this.loggingLevelCb = new System.Windows.Forms.ComboBox();
this.advancedSettingsGb.SuspendLayout();
this.booksGb.SuspendLayout();
this.SuspendLayout();
//
// booksLocationLbl
//
this.booksLocationLbl.AutoSize = true;
this.booksLocationLbl.Location = new System.Drawing.Point(14, 20);
this.booksLocationLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.booksLocationLbl.Name = "booksLocationLbl";
this.booksLocationLbl.Size = new System.Drawing.Size(85, 15);
this.booksLocationLbl.TabIndex = 0;
this.booksLocationLbl.Text = "Books location";
//
// booksLocationTb
//
this.booksLocationTb.Location = new System.Drawing.Point(111, 16);
this.booksLocationTb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.booksLocationTb.Name = "booksLocationTb";
this.booksLocationTb.Size = new System.Drawing.Size(760, 23);
this.booksLocationTb.TabIndex = 1;
//
// booksLocationSearchBtn
//
this.booksLocationSearchBtn.Location = new System.Drawing.Point(878, 14);
this.booksLocationSearchBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.booksLocationSearchBtn.Name = "booksLocationSearchBtn";
this.booksLocationSearchBtn.Size = new System.Drawing.Size(41, 27);
this.booksLocationSearchBtn.TabIndex = 2;
this.booksLocationSearchBtn.Text = "...";
this.booksLocationSearchBtn.UseVisualStyleBackColor = true;
this.booksLocationSearchBtn.Click += new System.EventHandler(this.booksLocationSearchBtn_Click);
//
// booksLocationDescLbl
//
this.booksLocationDescLbl.AutoSize = true;
this.booksLocationDescLbl.Location = new System.Drawing.Point(107, 43);
this.booksLocationDescLbl.Location = new System.Drawing.Point(7, 19);
this.booksLocationDescLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.booksLocationDescLbl.Name = "booksLocationDescLbl";
this.booksLocationDescLbl.Size = new System.Drawing.Size(39, 15);
this.booksLocationDescLbl.TabIndex = 3;
this.booksLocationDescLbl.Text = "[desc]";
this.booksLocationDescLbl.Size = new System.Drawing.Size(69, 15);
this.booksLocationDescLbl.TabIndex = 2;
this.booksLocationDescLbl.Text = "[book desc]";
//
// downloadsInProgressGb
// inProgressDescLbl
//
this.downloadsInProgressGb.Controls.Add(this.downloadsInProgressLibationFilesRb);
this.downloadsInProgressGb.Controls.Add(this.downloadsInProgressWinTempRb);
this.downloadsInProgressGb.Controls.Add(this.downloadsInProgressDescLbl);
this.downloadsInProgressGb.Location = new System.Drawing.Point(10, 49);
this.downloadsInProgressGb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.downloadsInProgressGb.Name = "downloadsInProgressGb";
this.downloadsInProgressGb.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.downloadsInProgressGb.Size = new System.Drawing.Size(884, 135);
this.downloadsInProgressGb.TabIndex = 4;
this.downloadsInProgressGb.TabStop = false;
this.downloadsInProgressGb.Text = "Downloads in progress";
//
// downloadsInProgressLibationFilesRb
//
this.downloadsInProgressLibationFilesRb.AutoSize = true;
this.downloadsInProgressLibationFilesRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.downloadsInProgressLibationFilesRb.Location = new System.Drawing.Point(10, 93);
this.downloadsInProgressLibationFilesRb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.downloadsInProgressLibationFilesRb.Name = "downloadsInProgressLibationFilesRb";
this.downloadsInProgressLibationFilesRb.Size = new System.Drawing.Size(215, 34);
this.downloadsInProgressLibationFilesRb.TabIndex = 2;
this.downloadsInProgressLibationFilesRb.TabStop = true;
this.downloadsInProgressLibationFilesRb.Text = "[desc]\r\n[libationFiles\\DownloadsInProgress]";
this.downloadsInProgressLibationFilesRb.UseVisualStyleBackColor = true;
//
// downloadsInProgressWinTempRb
//
this.downloadsInProgressWinTempRb.AutoSize = true;
this.downloadsInProgressWinTempRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.downloadsInProgressWinTempRb.Location = new System.Drawing.Point(10, 52);
this.downloadsInProgressWinTempRb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.downloadsInProgressWinTempRb.Name = "downloadsInProgressWinTempRb";
this.downloadsInProgressWinTempRb.Size = new System.Drawing.Size(200, 34);
this.downloadsInProgressWinTempRb.TabIndex = 1;
this.downloadsInProgressWinTempRb.TabStop = true;
this.downloadsInProgressWinTempRb.Text = "[desc]\r\n[winTemp\\DownloadsInProgress]";
this.downloadsInProgressWinTempRb.UseVisualStyleBackColor = true;
//
// downloadsInProgressDescLbl
//
this.downloadsInProgressDescLbl.AutoSize = true;
this.downloadsInProgressDescLbl.Location = new System.Drawing.Point(7, 18);
this.downloadsInProgressDescLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.downloadsInProgressDescLbl.Name = "downloadsInProgressDescLbl";
this.downloadsInProgressDescLbl.Size = new System.Drawing.Size(43, 30);
this.downloadsInProgressDescLbl.TabIndex = 0;
this.downloadsInProgressDescLbl.Text = "[desc]\r\n[line 2]";
//
// decryptInProgressGb
//
this.decryptInProgressGb.Controls.Add(this.decryptInProgressLibationFilesRb);
this.decryptInProgressGb.Controls.Add(this.decryptInProgressWinTempRb);
this.decryptInProgressGb.Controls.Add(this.decryptInProgressDescLbl);
this.decryptInProgressGb.Location = new System.Drawing.Point(10, 193);
this.decryptInProgressGb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.decryptInProgressGb.Name = "decryptInProgressGb";
this.decryptInProgressGb.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.decryptInProgressGb.Size = new System.Drawing.Size(884, 135);
this.decryptInProgressGb.TabIndex = 5;
this.decryptInProgressGb.TabStop = false;
this.decryptInProgressGb.Text = "Decrypt in progress";
//
// decryptInProgressLibationFilesRb
//
this.decryptInProgressLibationFilesRb.AutoSize = true;
this.decryptInProgressLibationFilesRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.decryptInProgressLibationFilesRb.Location = new System.Drawing.Point(7, 93);
this.decryptInProgressLibationFilesRb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.decryptInProgressLibationFilesRb.Name = "decryptInProgressLibationFilesRb";
this.decryptInProgressLibationFilesRb.Size = new System.Drawing.Size(197, 34);
this.decryptInProgressLibationFilesRb.TabIndex = 2;
this.decryptInProgressLibationFilesRb.TabStop = true;
this.decryptInProgressLibationFilesRb.Text = "[desc]\r\n[libationFiles\\DecryptInProgress]";
this.decryptInProgressLibationFilesRb.UseVisualStyleBackColor = true;
//
// decryptInProgressWinTempRb
//
this.decryptInProgressWinTempRb.AutoSize = true;
this.decryptInProgressWinTempRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.decryptInProgressWinTempRb.Location = new System.Drawing.Point(7, 52);
this.decryptInProgressWinTempRb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.decryptInProgressWinTempRb.Name = "decryptInProgressWinTempRb";
this.decryptInProgressWinTempRb.Size = new System.Drawing.Size(182, 34);
this.decryptInProgressWinTempRb.TabIndex = 1;
this.decryptInProgressWinTempRb.TabStop = true;
this.decryptInProgressWinTempRb.Text = "[desc]\r\n[winTemp\\DecryptInProgress]";
this.decryptInProgressWinTempRb.UseVisualStyleBackColor = true;
//
// decryptInProgressDescLbl
//
this.decryptInProgressDescLbl.AutoSize = true;
this.decryptInProgressDescLbl.Location = new System.Drawing.Point(7, 18);
this.decryptInProgressDescLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.decryptInProgressDescLbl.Name = "decryptInProgressDescLbl";
this.decryptInProgressDescLbl.Size = new System.Drawing.Size(43, 30);
this.decryptInProgressDescLbl.TabIndex = 0;
this.decryptInProgressDescLbl.Text = "[desc]\r\n[line 2]";
this.inProgressDescLbl.AutoSize = true;
this.inProgressDescLbl.Location = new System.Drawing.Point(8, 127);
this.inProgressDescLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.inProgressDescLbl.Name = "inProgressDescLbl";
this.inProgressDescLbl.Size = new System.Drawing.Size(43, 45);
this.inProgressDescLbl.TabIndex = 1;
this.inProgressDescLbl.Text = "[desc]\r\n[line 2]\r\n[line 3]";
//
// saveBtn
//
this.saveBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.saveBtn.Location = new System.Drawing.Point(714, 401);
this.saveBtn.Location = new System.Drawing.Point(714, 419);
this.saveBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.saveBtn.Name = "saveBtn";
this.saveBtn.Size = new System.Drawing.Size(88, 27);
this.saveBtn.TabIndex = 7;
this.saveBtn.TabIndex = 4;
this.saveBtn.Text = "Save";
this.saveBtn.UseVisualStyleBackColor = true;
this.saveBtn.Click += new System.EventHandler(this.saveBtn_Click);
@@ -204,38 +82,126 @@
//
this.cancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelBtn.Location = new System.Drawing.Point(832, 401);
this.cancelBtn.Location = new System.Drawing.Point(832, 419);
this.cancelBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.cancelBtn.Name = "cancelBtn";
this.cancelBtn.Size = new System.Drawing.Size(88, 27);
this.cancelBtn.TabIndex = 8;
this.cancelBtn.TabIndex = 5;
this.cancelBtn.Text = "Cancel";
this.cancelBtn.UseVisualStyleBackColor = true;
this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click);
//
// groupBox1
// advancedSettingsGb
//
this.groupBox1.Controls.Add(this.allowLibationFixupCbox);
this.groupBox1.Controls.Add(this.downloadsInProgressGb);
this.groupBox1.Controls.Add(this.decryptInProgressGb);
this.groupBox1.Location = new System.Drawing.Point(18, 61);
this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.groupBox1.Size = new System.Drawing.Size(902, 334);
this.groupBox1.TabIndex = 6;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Advanced settings for control freaks";
this.advancedSettingsGb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.advancedSettingsGb.Controls.Add(this.convertLossyRb);
this.advancedSettingsGb.Controls.Add(this.convertLosslessRb);
this.advancedSettingsGb.Controls.Add(this.inProgressSelectControl);
this.advancedSettingsGb.Controls.Add(this.allowLibationFixupCbox);
this.advancedSettingsGb.Controls.Add(this.inProgressDescLbl);
this.advancedSettingsGb.Location = new System.Drawing.Point(12, 176);
this.advancedSettingsGb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.advancedSettingsGb.Name = "advancedSettingsGb";
this.advancedSettingsGb.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.advancedSettingsGb.Size = new System.Drawing.Size(908, 232);
this.advancedSettingsGb.TabIndex = 5;
this.advancedSettingsGb.TabStop = false;
this.advancedSettingsGb.Text = "Advanced settings for control freaks";
//
// convertLossyRb
//
this.convertLossyRb.AutoSize = true;
this.convertLossyRb.Location = new System.Drawing.Point(7, 88);
this.convertLossyRb.Name = "convertLossyRb";
this.convertLossyRb.Size = new System.Drawing.Size(242, 19);
this.convertLossyRb.TabIndex = 0;
this.convertLossyRb.Text = "Download my books as .MP3 files (Lossy)";
this.convertLossyRb.UseVisualStyleBackColor = true;
//
// convertLosslessRb
//
this.convertLosslessRb.AutoSize = true;
this.convertLosslessRb.Checked = true;
this.convertLosslessRb.Location = new System.Drawing.Point(7, 63);
this.convertLosslessRb.Name = "convertLosslessRb";
this.convertLosslessRb.Size = new System.Drawing.Size(327, 19);
this.convertLosslessRb.TabIndex = 0;
this.convertLosslessRb.TabStop = true;
this.convertLosslessRb.Text = "Download my books as .M4B files (Lossless Mp4a format)";
this.convertLosslessRb.UseVisualStyleBackColor = true;
//
// inProgressSelectControl
//
this.inProgressSelectControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.inProgressSelectControl.Location = new System.Drawing.Point(10, 175);
this.inProgressSelectControl.Name = "inProgressSelectControl";
this.inProgressSelectControl.Size = new System.Drawing.Size(552, 52);
this.inProgressSelectControl.TabIndex = 2;
//
// allowLibationFixupCbox
//
this.allowLibationFixupCbox.AutoSize = true;
this.allowLibationFixupCbox.Location = new System.Drawing.Point(10, 24);
this.allowLibationFixupCbox.Checked = true;
this.allowLibationFixupCbox.CheckState = System.Windows.Forms.CheckState.Checked;
this.allowLibationFixupCbox.Location = new System.Drawing.Point(7, 22);
this.allowLibationFixupCbox.Name = "allowLibationFixupCbox";
this.allowLibationFixupCbox.Size = new System.Drawing.Size(262, 19);
this.allowLibationFixupCbox.TabIndex = 6;
this.allowLibationFixupCbox.TabIndex = 0;
this.allowLibationFixupCbox.Text = "Allow Libation to fix up audiobook metadata";
this.allowLibationFixupCbox.UseVisualStyleBackColor = true;
this.allowLibationFixupCbox.CheckedChanged += new System.EventHandler(this.allowLibationFixupCbox_CheckedChanged);
//
// logsBtn
//
this.logsBtn.Location = new System.Drawing.Point(262, 147);
this.logsBtn.Name = "logsBtn";
this.logsBtn.Size = new System.Drawing.Size(132, 23);
this.logsBtn.TabIndex = 4;
this.logsBtn.Text = "Open log folder";
this.logsBtn.UseVisualStyleBackColor = true;
this.logsBtn.Click += new System.EventHandler(this.logsBtn_Click);
//
// booksSelectControl
//
this.booksSelectControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.booksSelectControl.Location = new System.Drawing.Point(7, 37);
this.booksSelectControl.Name = "booksSelectControl";
this.booksSelectControl.Size = new System.Drawing.Size(895, 87);
this.booksSelectControl.TabIndex = 1;
//
// booksGb
//
this.booksGb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.booksGb.Controls.Add(this.booksSelectControl);
this.booksGb.Controls.Add(this.booksLocationDescLbl);
this.booksGb.Location = new System.Drawing.Point(12, 12);
this.booksGb.Name = "booksGb";
this.booksGb.Size = new System.Drawing.Size(908, 129);
this.booksGb.TabIndex = 1;
this.booksGb.TabStop = false;
this.booksGb.Text = "Books location";
//
// loggingLevelLbl
//
this.loggingLevelLbl.AutoSize = true;
this.loggingLevelLbl.Location = new System.Drawing.Point(12, 150);
this.loggingLevelLbl.Name = "loggingLevelLbl";
this.loggingLevelLbl.Size = new System.Drawing.Size(78, 15);
this.loggingLevelLbl.TabIndex = 2;
this.loggingLevelLbl.Text = "Logging level";
//
// loggingLevelCb
//
this.loggingLevelCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.loggingLevelCb.FormattingEnabled = true;
this.loggingLevelCb.Location = new System.Drawing.Point(96, 147);
this.loggingLevelCb.Name = "loggingLevelCb";
this.loggingLevelCb.Size = new System.Drawing.Size(129, 23);
this.loggingLevelCb.TabIndex = 3;
//
// SettingsDialog
//
@@ -243,47 +209,43 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.cancelBtn;
this.ClientSize = new System.Drawing.Size(933, 442);
this.Controls.Add(this.groupBox1);
this.ClientSize = new System.Drawing.Size(933, 462);
this.Controls.Add(this.logsBtn);
this.Controls.Add(this.loggingLevelCb);
this.Controls.Add(this.loggingLevelLbl);
this.Controls.Add(this.booksGb);
this.Controls.Add(this.advancedSettingsGb);
this.Controls.Add(this.cancelBtn);
this.Controls.Add(this.saveBtn);
this.Controls.Add(this.booksLocationDescLbl);
this.Controls.Add(this.booksLocationSearchBtn);
this.Controls.Add(this.booksLocationTb);
this.Controls.Add(this.booksLocationLbl);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.Name = "SettingsDialog";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Edit Settings";
this.Load += new System.EventHandler(this.SettingsDialog_Load);
this.downloadsInProgressGb.ResumeLayout(false);
this.downloadsInProgressGb.PerformLayout();
this.decryptInProgressGb.ResumeLayout(false);
this.decryptInProgressGb.PerformLayout();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.advancedSettingsGb.ResumeLayout(false);
this.advancedSettingsGb.PerformLayout();
this.booksGb.ResumeLayout(false);
this.booksGb.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label booksLocationLbl;
private System.Windows.Forms.TextBox booksLocationTb;
private System.Windows.Forms.Button booksLocationSearchBtn;
private System.Windows.Forms.Label booksLocationDescLbl;
private System.Windows.Forms.GroupBox downloadsInProgressGb;
private System.Windows.Forms.Label downloadsInProgressDescLbl;
private System.Windows.Forms.RadioButton downloadsInProgressWinTempRb;
private System.Windows.Forms.RadioButton downloadsInProgressLibationFilesRb;
private System.Windows.Forms.GroupBox decryptInProgressGb;
private System.Windows.Forms.Label decryptInProgressDescLbl;
private System.Windows.Forms.RadioButton decryptInProgressLibationFilesRb;
private System.Windows.Forms.RadioButton decryptInProgressWinTempRb;
private System.Windows.Forms.Label inProgressDescLbl;
private System.Windows.Forms.Button saveBtn;
private System.Windows.Forms.Button cancelBtn;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.GroupBox advancedSettingsGb;
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.GroupBox booksGb;
private System.Windows.Forms.Button logsBtn;
private System.Windows.Forms.Label loggingLevelLbl;
private System.Windows.Forms.ComboBox loggingLevelCb;
}
}

View File

@@ -18,72 +18,97 @@ namespace LibationWinForms.Dialogs
if (this.DesignMode)
return;
{
loggingLevelCb.Items.Clear();
foreach (var level in Enum<Serilog.Events.LogEventLevel>.GetValues())
loggingLevelCb.Items.Add(level);
loggingLevelCb.SelectedItem = config.LogLevel;
}
this.booksLocationDescLbl.Text = desc(nameof(config.Books));
this.downloadsInProgressDescLbl.Text = desc(nameof(config.DownloadsInProgressEnum));
this.decryptInProgressDescLbl.Text = desc(nameof(config.DecryptInProgressEnum));
this.inProgressDescLbl.Text = desc(nameof(config.InProgress));
var winTempText = "In your Windows temporary folder\r\n";
this.downloadsInProgressWinTempRb.Text = $"{winTempText}{Path.Combine(Configuration.WinTemp, "DownloadsInProgress")}";
this.decryptInProgressWinTempRb.Text = $"{winTempText}{Path.Combine(Configuration.WinTemp, "DecryptInProgress")}";
var libFileText = "In your Libation Files (ie: program-created files)\r\n";
this.downloadsInProgressLibationFilesRb.Text = $"{libFileText}{Path.Combine(config.LibationFiles, "DownloadsInProgress")}";
this.decryptInProgressLibationFilesRb.Text = $"{libFileText}{Path.Combine(config.LibationFiles, "DecryptInProgress")}";
this.booksLocationTb.Text
= !string.IsNullOrWhiteSpace(config.Books)
? config.Books
: Path.GetDirectoryName(Exe.FileLocationOnDisk);
booksSelectControl.SetSearchTitle("books location");
booksSelectControl.SetDirectoryItems(
new()
{
Configuration.KnownDirectories.UserProfile,
Configuration.KnownDirectories.AppDir,
Configuration.KnownDirectories.MyDocs
},
Configuration.KnownDirectories.UserProfile,
"Books");
booksSelectControl.SelectDirectory(config.Books);
allowLibationFixupCbox.Checked = config.AllowLibationFixup;
convertLosslessRb.Checked = !config.DecryptToLossy;
convertLossyRb.Checked = config.DecryptToLossy;
switch (config.DownloadsInProgressEnum)
{
case Configuration.LIBATION_FILES_LABEL:
downloadsInProgressLibationFilesRb.Checked = true;
break;
case Configuration.WIN_TEMP_LABEL:
default:
downloadsInProgressWinTempRb.Checked = true;
break;
}
allowLibationFixupCbox_CheckedChanged(this, e);
switch (config.DecryptInProgressEnum)
inProgressSelectControl.SetDirectoryItems(new()
{
case Configuration.LIBATION_FILES_LABEL:
decryptInProgressLibationFilesRb.Checked = true;
break;
case Configuration.WIN_TEMP_LABEL:
default:
decryptInProgressWinTempRb.Checked = true;
break;
Configuration.KnownDirectories.WinTemp,
Configuration.KnownDirectories.UserProfile,
Configuration.KnownDirectories.AppDir,
Configuration.KnownDirectories.MyDocs,
Configuration.KnownDirectories.LibationFiles
}, Configuration.KnownDirectories.WinTemp);
inProgressSelectControl.SelectDirectory(config.InProgress);
}
private void allowLibationFixupCbox_CheckedChanged(object sender, EventArgs e)
{
convertLosslessRb.Enabled = allowLibationFixupCbox.Checked;
convertLossyRb.Enabled = allowLibationFixupCbox.Checked;
if (!allowLibationFixupCbox.Checked)
{
convertLosslessRb.Checked = true;
}
}
private void booksLocationSearchBtn_Click(object sender, EventArgs e) => selectFolder("Search for books location", this.booksLocationTb);
private static void selectFolder(string desc, TextBox textbox)
{
using var dialog = new FolderBrowserDialog { Description = desc, SelectedPath = "" };
dialog.ShowDialog();
if (!string.IsNullOrWhiteSpace(dialog.SelectedPath))
textbox.Text = dialog.SelectedPath;
}
private void logsBtn_Click(object sender, EventArgs e) => Go.To.Folder(Configuration.Instance.LibationFiles);
private void saveBtn_Click(object sender, EventArgs e)
{
config.AllowLibationFixup = allowLibationFixupCbox.Checked;
config.DownloadsInProgressEnum = downloadsInProgressLibationFilesRb.Checked ? Configuration.LIBATION_FILES_LABEL : Configuration.WIN_TEMP_LABEL;
config.DecryptInProgressEnum = decryptInProgressLibationFilesRb.Checked ? Configuration.LIBATION_FILES_LABEL : Configuration.WIN_TEMP_LABEL;
var newBooks = booksSelectControl.SelectedDirectory;
var newBooks = this.booksLocationTb.Text;
if (!Directory.Exists(newBooks))
if (string.IsNullOrWhiteSpace(newBooks))
{
MessageBox.Show($"Not saving change to Books location. This folder does not exist:\r\n{newBooks}");
MessageBox.Show("Cannot set Books Location to blank", "Location is blank", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
else
config.Books = newBooks;
if (!Directory.Exists(newBooks))
{
if (booksSelectControl.SelectedDirectoryIsCustom)
{
MessageBox.Show($"Not saving change to Books location. This folder does not exist:\r\n{newBooks}", "Folder does not exist", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (booksSelectControl.SelectedDirectoryIsKnown)
Directory.CreateDirectory(newBooks);
}
config.Books = newBooks;
{
var logLevelOld = config.LogLevel;
var logLevelNew = (Serilog.Events.LogEventLevel)loggingLevelCb.SelectedItem;
config.LogLevel = logLevelNew;
// only warn if changed during this time. don't want to warn every time user happens to change settings while level is verbose
if (logLevelOld != logLevelNew)
MessageBoxVerboseLoggingWarning.ShowIfTrue();
}
config.AllowLibationFixup = allowLibationFixupCbox.Checked;
config.DecryptToLossy = convertLossyRb.Checked;
config.InProgress = inProgressSelectControl.SelectedDirectory;
this.DialogResult = DialogResult.OK;
this.Close();

View File

@@ -57,67 +57,4 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="booksLocationLbl.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="booksLocationTb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="booksLocationSearchBtn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="booksLocationDescLbl.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="downloadsInProgressGb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="downloadsInProgressLibationFilesRb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="downloadsInProgressWinTempRb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="downloadsInProgressDescLbl.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="downloadsInProgressLibationFilesRb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="downloadsInProgressWinTempRb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="downloadsInProgressDescLbl.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="decryptInProgressGb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="decryptInProgressLibationFilesRb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="decryptInProgressWinTempRb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="decryptInProgressDescLbl.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="decryptInProgressLibationFilesRb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="decryptInProgressWinTempRb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="decryptInProgressDescLbl.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="saveBtn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="cancelBtn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="groupBox1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

View File

@@ -30,63 +30,57 @@
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SetupDialog));
this.welcomeLbl = new System.Windows.Forms.Label();
this.noQuestionsBtn = new System.Windows.Forms.Button();
this.basicBtn = new System.Windows.Forms.Button();
this.advancedBtn = new System.Windows.Forms.Button();
this.newUserBtn = new System.Windows.Forms.Button();
this.returningUserBtn = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// welcomeLbl
//
this.welcomeLbl.AutoSize = true;
this.welcomeLbl.Location = new System.Drawing.Point(12, 9);
this.welcomeLbl.Location = new System.Drawing.Point(14, 10);
this.welcomeLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.welcomeLbl.Name = "welcomeLbl";
this.welcomeLbl.Size = new System.Drawing.Size(399, 117);
this.welcomeLbl.Size = new System.Drawing.Size(449, 135);
this.welcomeLbl.TabIndex = 0;
this.welcomeLbl.Text = resources.GetString("welcomeLbl.Text");
//
// noQuestionsBtn
// newUserBtn
//
this.noQuestionsBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.noQuestionsBtn.Location = new System.Drawing.Point(15, 129);
this.noQuestionsBtn.Name = "noQuestionsBtn";
this.noQuestionsBtn.Size = new System.Drawing.Size(396, 57);
this.noQuestionsBtn.TabIndex = 1;
this.noQuestionsBtn.Text = "NO-QUESTIONS SETUP\r\n\r\nAccept all defaults";
this.noQuestionsBtn.UseVisualStyleBackColor = true;
this.newUserBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.newUserBtn.Location = new System.Drawing.Point(18, 156);
this.newUserBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.newUserBtn.Name = "newUserBtn";
this.newUserBtn.Size = new System.Drawing.Size(462, 66);
this.newUserBtn.TabIndex = 2;
this.newUserBtn.Text = "NEW USER\r\n\r\nChoose settings";
this.newUserBtn.UseVisualStyleBackColor = true;
this.newUserBtn.Click += new System.EventHandler(this.newUserBtn_Click);
//
// basicBtn
// returningUserBtn
//
this.basicBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.basicBtn.Location = new System.Drawing.Point(15, 192);
this.basicBtn.Name = "basicBtn";
this.basicBtn.Size = new System.Drawing.Size(396, 57);
this.basicBtn.TabIndex = 2;
this.basicBtn.Text = "BASIC SETUP\r\n\r\nChoose settings";
this.basicBtn.UseVisualStyleBackColor = true;
//
// advancedBtn
//
this.advancedBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.advancedBtn.Location = new System.Drawing.Point(15, 255);
this.advancedBtn.Name = "advancedBtn";
this.advancedBtn.Size = new System.Drawing.Size(396, 57);
this.advancedBtn.TabIndex = 3;
this.advancedBtn.Text = "ADVANCED SETUP\r\n\r\nChoose settings and where to store them";
this.advancedBtn.UseVisualStyleBackColor = true;
this.returningUserBtn.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.returningUserBtn.Location = new System.Drawing.Point(18, 228);
this.returningUserBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.returningUserBtn.Name = "returningUserBtn";
this.returningUserBtn.Size = new System.Drawing.Size(462, 66);
this.returningUserBtn.TabIndex = 3;
this.returningUserBtn.Text = "RETURNING USER\r\n\r\nI have previously installed Libation. This is an upgrade or re-" +
"install";
this.returningUserBtn.UseVisualStyleBackColor = true;
this.returningUserBtn.Click += new System.EventHandler(this.returningUserBtn_Click);
//
// SetupDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(423, 324);
this.Controls.Add(this.advancedBtn);
this.Controls.Add(this.basicBtn);
this.Controls.Add(this.noQuestionsBtn);
this.ClientSize = new System.Drawing.Size(493, 308);
this.Controls.Add(this.returningUserBtn);
this.Controls.Add(this.newUserBtn);
this.Controls.Add(this.welcomeLbl);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.Name = "SetupDialog";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Welcome to Libation";
@@ -98,8 +92,7 @@
#endregion
private System.Windows.Forms.Label welcomeLbl;
private System.Windows.Forms.Button noQuestionsBtn;
private System.Windows.Forms.Button basicBtn;
private System.Windows.Forms.Button advancedBtn;
private System.Windows.Forms.Button newUserBtn;
private System.Windows.Forms.Button returningUserBtn;
}
}

View File

@@ -5,33 +5,25 @@ namespace LibationWinForms.Dialogs
{
public partial class SetupDialog : Form
{
public event EventHandler NoQuestionsBtn_Click
public bool IsNewUser { get; private set; }
public bool IsReturningUser { get; private set; }
public SetupDialog() => InitializeComponent();
private void newUserBtn_Click(object sender, EventArgs e)
{
add => noQuestionsBtn.Click += value;
remove => noQuestionsBtn.Click -= value;
IsNewUser = true;
this.DialogResult = DialogResult.OK;
Close();
}
public event EventHandler BasicBtn_Click
private void returningUserBtn_Click(object sender, EventArgs e)
{
add => basicBtn.Click += value;
remove => basicBtn.Click -= value;
IsReturningUser = true;
this.DialogResult = DialogResult.OK;
Close();
}
public event EventHandler AdvancedBtn_Click
{
add => advancedBtn.Click += value;
remove => advancedBtn.Click -= value;
}
public SetupDialog()
{
InitializeComponent();
noQuestionsBtn.Click += btn_Click;
basicBtn.Click += btn_Click;
advancedBtn.Click += btn_Click;
}
private void btn_Click(object sender, EventArgs e) => Close();
}
}

View File

@@ -66,6 +66,6 @@ After you make your selections, get started by importing your library.
Go to Import &gt; Scan Library
Download your entire library from the "Liberate" tab or
liberate your books one at a time by clicking the stoplight</value>
liberate your books one at a time by clicking the stoplight.</value>
</data>
</root>

View File

@@ -1,81 +0,0 @@

namespace LibationWinForms.Dialogs
{
partial class TEMP_TestNewControls
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.directorySelectControl1 = new LibationWinForms.Dialogs.DirectorySelectControl();
this.directoryOrCustomSelectControl1 = new LibationWinForms.Dialogs.DirectoryOrCustomSelectControl();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(438, 375);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 2;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// directorySelectControl1
//
this.directorySelectControl1.Location = new System.Drawing.Point(30, 54);
this.directorySelectControl1.Name = "directorySelectControl1";
this.directorySelectControl1.Size = new System.Drawing.Size(758, 46);
this.directorySelectControl1.TabIndex = 4;
//
// directoryOrCustomSelectControl1
//
this.directoryOrCustomSelectControl1.Location = new System.Drawing.Point(128, 199);
this.directoryOrCustomSelectControl1.Name = "directoryOrCustomSelectControl1";
this.directoryOrCustomSelectControl1.Size = new System.Drawing.Size(660, 81);
this.directoryOrCustomSelectControl1.TabIndex = 5;
//
// TEMP_TestNewControls
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.directoryOrCustomSelectControl1);
this.Controls.Add(this.directorySelectControl1);
this.Controls.Add(this.button1);
this.Name = "TEMP_TestNewControls";
this.Text = "TEMP_TestNewControls";
this.Load += new System.EventHandler(this.TEMP_TestNewControls_Load);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
private DirectorySelectControl directorySelectControl1;
private DirectoryOrCustomSelectControl directoryOrCustomSelectControl1;
}
}

View File

@@ -1,89 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LibationWinForms.Dialogs
{
public partial class TEMP_TestNewControls : Form
{
public TEMP_TestNewControls()
{
InitializeComponent();
}
private void TEMP_TestNewControls_Load(object sender, EventArgs e)
{
if (this.DesignMode)
return;
{
var dirCtrl = this.directorySelectControl1;
dirCtrl.SetDirectoryItems(new()
{
FileManager.Configuration.KnownDirectories.AppDir,
FileManager.Configuration.KnownDirectories.MyDocs,
FileManager.Configuration.KnownDirectories.LibationFiles,
FileManager.Configuration.KnownDirectories.MyDocs,
FileManager.Configuration.KnownDirectories.None,
FileManager.Configuration.KnownDirectories.WinTemp,
FileManager.Configuration.KnownDirectories.UserProfile
}
,
FileManager.Configuration.KnownDirectories.MyDocs
);
}
{
var dirOrCustCtrl = this.directoryOrCustomSelectControl1;
dirOrCustCtrl.SetSearchTitle("Libation Files");
dirOrCustCtrl.SetDirectoryItems(new()
{
FileManager.Configuration.KnownDirectories.AppDir,
FileManager.Configuration.KnownDirectories.MyDocs,
FileManager.Configuration.KnownDirectories.LibationFiles,
FileManager.Configuration.KnownDirectories.MyDocs,
FileManager.Configuration.KnownDirectories.None,
FileManager.Configuration.KnownDirectories.WinTemp,
FileManager.Configuration.KnownDirectories.UserProfile
}
,
FileManager.Configuration.KnownDirectories.MyDocs
);
}
}
private void button1_Click(object sender, EventArgs e)
{
var dirCtrl = this.directorySelectControl1;
var x = dirCtrl.SelectedDirectory;
dirCtrl.SelectDirectory(FileManager.Configuration.KnownDirectories.UserProfile);
var dirOrCustCtrl = this.directoryOrCustomSelectControl1;
var y = dirOrCustCtrl.SelectedDirectory;
dirOrCustCtrl.SelectDirectory(FileManager.Configuration.KnownDirectories.UserProfile);
}
}
}

View File

@@ -43,6 +43,7 @@
this.beginBookBackupsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.beginPdfBackupsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.quickFiltersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.firstFilterIsDefaultToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.editQuickFiltersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -50,34 +51,33 @@
this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.accountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.basicSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.advancedSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.visibleCountLbl = new System.Windows.Forms.ToolStripStatusLabel();
this.springLbl = new System.Windows.Forms.ToolStripStatusLabel();
this.backupsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel();
this.pdfsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel();
this.addFilterBtn = new System.Windows.Forms.Button();
this.noAccountsYetAddAccountToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip1.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.SuspendLayout();
//
// gridPanel
//
this.gridPanel.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.gridPanel.Location = new System.Drawing.Point(12, 56);
this.gridPanel.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.gridPanel.Location = new System.Drawing.Point(14, 65);
this.gridPanel.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.gridPanel.Name = "gridPanel";
this.gridPanel.Size = new System.Drawing.Size(839, 386);
this.gridPanel.Size = new System.Drawing.Size(979, 445);
this.gridPanel.TabIndex = 5;
//
// filterHelpBtn
//
this.filterHelpBtn.Location = new System.Drawing.Point(12, 27);
this.filterHelpBtn.Location = new System.Drawing.Point(14, 31);
this.filterHelpBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.filterHelpBtn.Name = "filterHelpBtn";
this.filterHelpBtn.Size = new System.Drawing.Size(22, 23);
this.filterHelpBtn.Size = new System.Drawing.Size(26, 27);
this.filterHelpBtn.TabIndex = 3;
this.filterHelpBtn.Text = "?";
this.filterHelpBtn.UseVisualStyleBackColor = true;
@@ -86,9 +86,10 @@
// filterBtn
//
this.filterBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.filterBtn.Location = new System.Drawing.Point(776, 27);
this.filterBtn.Location = new System.Drawing.Point(905, 31);
this.filterBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.filterBtn.Name = "filterBtn";
this.filterBtn.Size = new System.Drawing.Size(75, 23);
this.filterBtn.Size = new System.Drawing.Size(88, 27);
this.filterBtn.TabIndex = 2;
this.filterBtn.Text = "Filter";
this.filterBtn.UseVisualStyleBackColor = true;
@@ -96,34 +97,36 @@
//
// filterSearchTb
//
this.filterSearchTb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.filterSearchTb.Location = new System.Drawing.Point(186, 29);
this.filterSearchTb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.filterSearchTb.Location = new System.Drawing.Point(217, 33);
this.filterSearchTb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.filterSearchTb.Name = "filterSearchTb";
this.filterSearchTb.Size = new System.Drawing.Size(584, 20);
this.filterSearchTb.Size = new System.Drawing.Size(681, 23);
this.filterSearchTb.TabIndex = 1;
this.filterSearchTb.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.filterSearchTb_KeyPress);
//
// menuStrip1
//
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.importToolStripMenuItem,
this.liberateToolStripMenuItem,
this.exportToolStripMenuItem,
this.quickFiltersToolStripMenuItem,
this.settingsToolStripMenuItem});
this.importToolStripMenuItem,
this.liberateToolStripMenuItem,
this.exportToolStripMenuItem,
this.quickFiltersToolStripMenuItem,
this.settingsToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(863, 24);
this.menuStrip1.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2);
this.menuStrip1.Size = new System.Drawing.Size(1007, 24);
this.menuStrip1.TabIndex = 0;
this.menuStrip1.Text = "menuStrip1";
//
// importToolStripMenuItem
//
this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.noAccountsYetAddAccountToolStripMenuItem,
this.scanLibraryToolStripMenuItem,
this.scanLibraryOfAllAccountsToolStripMenuItem,
this.noAccountsYetAddAccountToolStripMenuItem,
this.scanLibraryToolStripMenuItem,
this.scanLibraryOfAllAccountsToolStripMenuItem,
this.scanLibraryOfSomeAccountsToolStripMenuItem});
this.importToolStripMenuItem.Name = "importToolStripMenuItem";
this.importToolStripMenuItem.Size = new System.Drawing.Size(55, 20);
@@ -134,6 +137,7 @@
this.noAccountsYetAddAccountToolStripMenuItem.Name = "noAccountsYetAddAccountToolStripMenuItem";
this.noAccountsYetAddAccountToolStripMenuItem.Size = new System.Drawing.Size(247, 22);
this.noAccountsYetAddAccountToolStripMenuItem.Text = "No accounts yet. A&dd Account...";
this.noAccountsYetAddAccountToolStripMenuItem.Click += new System.EventHandler(this.noAccountsYetAddAccountToolStripMenuItem_Click);
//
// scanLibraryToolStripMenuItem
//
@@ -159,8 +163,8 @@
// liberateToolStripMenuItem
//
this.liberateToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.beginBookBackupsToolStripMenuItem,
this.beginPdfBackupsToolStripMenuItem});
this.beginBookBackupsToolStripMenuItem,
this.beginPdfBackupsToolStripMenuItem});
this.liberateToolStripMenuItem.Name = "liberateToolStripMenuItem";
this.liberateToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
this.liberateToolStripMenuItem.Text = "&Liberate";
@@ -182,17 +186,24 @@
// exportToolStripMenuItem
//
this.exportToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.exportLibraryToolStripMenuItem});
this.exportLibraryToolStripMenuItem});
this.exportToolStripMenuItem.Name = "exportToolStripMenuItem";
this.exportToolStripMenuItem.Size = new System.Drawing.Size(53, 20);
this.exportToolStripMenuItem.Text = "E&xport";
//
// exportLibraryToolStripMenuItem
//
this.exportLibraryToolStripMenuItem.Name = "exportLibraryToolStripMenuItem";
this.exportLibraryToolStripMenuItem.Size = new System.Drawing.Size(156, 22);
this.exportLibraryToolStripMenuItem.Text = "E&xport Library...";
this.exportLibraryToolStripMenuItem.Click += new System.EventHandler(this.exportLibraryToolStripMenuItem_Click);
//
// quickFiltersToolStripMenuItem
//
this.quickFiltersToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.firstFilterIsDefaultToolStripMenuItem,
this.editQuickFiltersToolStripMenuItem,
this.toolStripSeparator1});
this.firstFilterIsDefaultToolStripMenuItem,
this.editQuickFiltersToolStripMenuItem,
this.toolStripSeparator1});
this.quickFiltersToolStripMenuItem.Name = "quickFiltersToolStripMenuItem";
this.quickFiltersToolStripMenuItem.Size = new System.Drawing.Size(84, 20);
this.quickFiltersToolStripMenuItem.Text = "Quick &Filters";
@@ -219,9 +230,8 @@
// settingsToolStripMenuItem
//
this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.accountsToolStripMenuItem,
this.basicSettingsToolStripMenuItem,
this.advancedSettingsToolStripMenuItem});
this.accountsToolStripMenuItem,
this.basicSettingsToolStripMenuItem});
this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
this.settingsToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
this.settingsToolStripMenuItem.Text = "&Settings";
@@ -229,34 +239,28 @@
// accountsToolStripMenuItem
//
this.accountsToolStripMenuItem.Name = "accountsToolStripMenuItem";
this.accountsToolStripMenuItem.Size = new System.Drawing.Size(181, 22);
this.accountsToolStripMenuItem.Size = new System.Drawing.Size(133, 22);
this.accountsToolStripMenuItem.Text = "&Accounts...";
this.accountsToolStripMenuItem.Click += new System.EventHandler(this.accountsToolStripMenuItem_Click);
//
// basicSettingsToolStripMenuItem
//
this.basicSettingsToolStripMenuItem.Name = "basicSettingsToolStripMenuItem";
this.basicSettingsToolStripMenuItem.Size = new System.Drawing.Size(181, 22);
this.basicSettingsToolStripMenuItem.Text = "&Basic Settings...";
this.basicSettingsToolStripMenuItem.Size = new System.Drawing.Size(133, 22);
this.basicSettingsToolStripMenuItem.Text = "&Settings...";
this.basicSettingsToolStripMenuItem.Click += new System.EventHandler(this.basicSettingsToolStripMenuItem_Click);
//
// advancedSettingsToolStripMenuItem
//
this.advancedSettingsToolStripMenuItem.Name = "advancedSettingsToolStripMenuItem";
this.advancedSettingsToolStripMenuItem.Size = new System.Drawing.Size(181, 22);
this.advancedSettingsToolStripMenuItem.Text = "Ad&vanced Settings...";
this.advancedSettingsToolStripMenuItem.Click += new System.EventHandler(this.advancedSettingsToolStripMenuItem_Click);
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.visibleCountLbl,
this.springLbl,
this.backupsCountsLbl,
this.pdfsCountsLbl});
this.statusStrip1.Location = new System.Drawing.Point(0, 445);
this.visibleCountLbl,
this.springLbl,
this.backupsCountsLbl,
this.pdfsCountsLbl});
this.statusStrip1.Location = new System.Drawing.Point(0, 517);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(863, 22);
this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 16, 0);
this.statusStrip1.Size = new System.Drawing.Size(1007, 22);
this.statusStrip1.TabIndex = 6;
this.statusStrip1.Text = "statusStrip1";
//
@@ -269,7 +273,7 @@
// springLbl
//
this.springLbl.Name = "springLbl";
this.springLbl.Size = new System.Drawing.Size(233, 17);
this.springLbl.Size = new System.Drawing.Size(375, 17);
this.springLbl.Spring = true;
//
// backupsCountsLbl
@@ -286,33 +290,20 @@
//
// addFilterBtn
//
this.addFilterBtn.Location = new System.Drawing.Point(40, 27);
this.addFilterBtn.Location = new System.Drawing.Point(47, 31);
this.addFilterBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.addFilterBtn.Name = "addFilterBtn";
this.addFilterBtn.Size = new System.Drawing.Size(140, 23);
this.addFilterBtn.Size = new System.Drawing.Size(163, 27);
this.addFilterBtn.TabIndex = 4;
this.addFilterBtn.Text = "Add To Quick Filters";
this.addFilterBtn.UseVisualStyleBackColor = true;
this.addFilterBtn.Click += new System.EventHandler(this.AddFilterBtn_Click);
//
// noAccountsYetAddAccountToolStripMenuItem
//
this.noAccountsYetAddAccountToolStripMenuItem.Name = "noAccountsYetAddAccountToolStripMenuItem";
this.noAccountsYetAddAccountToolStripMenuItem.Size = new System.Drawing.Size(247, 22);
this.noAccountsYetAddAccountToolStripMenuItem.Text = "No accounts yet. A&dd Account...";
this.noAccountsYetAddAccountToolStripMenuItem.Click += new System.EventHandler(this.noAccountsYetAddAccountToolStripMenuItem_Click);
//
// exportLibraryToolStripMenuItem
//
this.exportLibraryToolStripMenuItem.Name = "exportLibraryToolStripMenuItem";
this.exportLibraryToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
this.exportLibraryToolStripMenuItem.Text = "E&xport Library...";
this.exportLibraryToolStripMenuItem.Click += new System.EventHandler(this.exportLibraryToolStripMenuItem_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(863, 467);
this.ClientSize = new System.Drawing.Size(1007, 539);
this.Controls.Add(this.filterBtn);
this.Controls.Add(this.addFilterBtn);
this.Controls.Add(this.filterSearchTb);
@@ -322,8 +313,10 @@
this.Controls.Add(this.menuStrip1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MainMenuStrip = this.menuStrip1;
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.Name = "Form1";
this.Text = "Libation: Liberate your Library";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
this.Load += new System.EventHandler(this.Form1_Load);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
@@ -358,7 +351,6 @@
private System.Windows.Forms.ToolStripMenuItem editQuickFiltersToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.ToolStripMenuItem basicSettingsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem advancedSettingsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem accountsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem scanLibraryOfAllAccountsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem scanLibraryOfSomeAccountsToolStripMenuItem;

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using ApplicationServices;
using DataLayer;
@@ -33,6 +34,31 @@ namespace LibationWinForms
beginBookBackupsToolStripMenuItem_format = beginBookBackupsToolStripMenuItem.Text;
beginPdfBackupsToolStripMenuItem_format = beginPdfBackupsToolStripMenuItem.Text;
// after backing up formats: can set default/temp visible text
backupsCountsLbl.Text = "[Calculating backed up book quantities]";
pdfsCountsLbl.Text = "[Calculating backed up PDFs]";
setVisibleCount(null, 0);
if (this.DesignMode)
return;
// independent UI updates
this.Load += setBackupCountsAsync;
this.Load += (_, __) => RestoreSizeAndLocation();
this.Load += (_, __) => RefreshImportMenu();
// start background service
this.Load += (_, __) => startBackgroundImageDownloader();
}
private static void startBackgroundImageDownloader()
{
// load default/missing cover images. this will also initiate the background image downloader
var format = System.Drawing.Imaging.ImageFormat.Jpeg;
PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format));
PictureStorage.SetDefaultImage(PictureSize._300x300, Properties.Resources.default_cover_300x300.ToBytes(format));
PictureStorage.SetDefaultImage(PictureSize._500x500, Properties.Resources.default_cover_500x500.ToBytes(format));
}
private void Form1_Load(object sender, EventArgs e)
@@ -40,29 +66,89 @@ namespace LibationWinForms
if (this.DesignMode)
return;
// load default/missing cover images. this will also initiate the background image downloader
var format = System.Drawing.Imaging.ImageFormat.Jpeg;
PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format));
PictureStorage.SetDefaultImage(PictureSize._300x300, Properties.Resources.default_cover_300x300.ToBytes(format));
PictureStorage.SetDefaultImage(PictureSize._500x500, Properties.Resources.default_cover_500x500.ToBytes(format));
RefreshImportMenu();
setVisibleCount(null, 0);
reloadGrid();
reloadGrid();
// also applies filter. ONLY call AFTER loading grid
loadInitialQuickFilterState();
// init bottom counts
backupsCountsLbl.Text = "[Calculating backed up book quantities]";
pdfsCountsLbl.Text = "[Calculating backed up PDFs]";
setBackupCounts(null, null);
}
#region reload grid
bool isProcessingGridSelect = false;
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
SaveSizeAndLocation();
}
private void RestoreSizeAndLocation()
{
var config = Configuration.Instance;
var width = config.MainFormWidth;
var height = config.MainFormHeight;
// too small -- something must have gone wrong. use defaults
if (width < 25 || height < 25)
{
width = 1023;
height = 578;
}
// Fit to the current screen size in case the screen resolution changed since the size was last persisted
if (width > Screen.PrimaryScreen.WorkingArea.Width)
width = Screen.PrimaryScreen.WorkingArea.Width;
if (height > Screen.PrimaryScreen.WorkingArea.Height)
height = Screen.PrimaryScreen.WorkingArea.Height;
var x = config.MainFormX;
var y = config.MainFormY;
var rect = new System.Drawing.Rectangle(x, y, width, height);
// is proposed rect on a screen?
if (Screen.AllScreens.Any(screen => screen.WorkingArea.Contains(rect)))
{
this.StartPosition = FormStartPosition.Manual;
this.DesktopBounds = rect;
}
else
{
this.StartPosition = FormStartPosition.WindowsDefaultLocation;
this.Size = rect.Size;
}
// FINAL: for Maximized: start normal state, set size and location, THEN set max state
this.WindowState = config.MainFormIsMaximized ? FormWindowState.Maximized : FormWindowState.Normal;
}
private void SaveSizeAndLocation()
{
System.Drawing.Point location;
System.Drawing.Size size;
// save location and size if the state is normal
if (this.WindowState == FormWindowState.Normal)
{
location = this.Location;
size = this.Size;
}
else
{
// save the RestoreBounds if the form is minimized or maximized
location = this.RestoreBounds.Location;
size = this.RestoreBounds.Size;
}
var config = Configuration.Instance;
config.MainFormX = location.X;
config.MainFormY = location.Y;
config.MainFormWidth = size.Width;
config.MainFormHeight = size.Height;
config.MainFormIsMaximized = this.WindowState == FormWindowState.Maximized;
}
#region reload grid
bool isProcessingGridSelect = false;
private void reloadGrid()
{
// suppressed filter while init'ing UI
@@ -84,14 +170,14 @@ namespace LibationWinForms
{
gridPanel.Controls.Remove(currProductsGrid);
currProductsGrid.VisibleCountChanged -= setVisibleCount;
currProductsGrid.BackupCountsChanged -= setBackupCounts;
currProductsGrid.BackupCountsChanged -= setBackupCountsAsync;
currProductsGrid.Dispose();
}
currProductsGrid = new ProductsGrid { Dock = DockStyle.Fill };
currProductsGrid.VisibleCountChanged += setVisibleCount;
currProductsGrid.BackupCountsChanged += setBackupCounts;
gridPanel.Controls.Add(currProductsGrid);
currProductsGrid.BackupCountsChanged += setBackupCountsAsync;
gridPanel.UIThread(() => gridPanel.Controls.Add(currProductsGrid));
currProductsGrid.Display();
}
ResumeLayout();
@@ -103,15 +189,17 @@ namespace LibationWinForms
#endregion
#region bottom: backup counts
private void setBackupCounts(object _, object __)
private async void setBackupCountsAsync(object _, object __)
{
var books = DbContexts.GetContext()
.GetLibrary_Flat_NoTracking()
.Select(sp => sp.Book)
.ToList();
await Task.Run(() => {
var books = DbContexts.GetContext()
.GetLibrary_Flat_NoTracking()
.Select(sp => sp.Book)
.ToList();
setBookBackupCounts(books);
setPdfBackupCounts(books);
setBookBackupCounts(books);
setPdfBackupCounts(books);
});
}
enum AudioFileState { full, aax, none }
private void setBookBackupCounts(IEnumerable<Book> books)
@@ -338,8 +426,7 @@ namespace LibationWinForms
}
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, "Error attempting to export library");
MessageBox.Show("Error attempting to export your library. Error message:\r\n\r\n" + ex.Message, "Error exporting", MessageBoxButtons.OK, MessageBoxIcon.Error);
MessageBoxAlertAdmin.Show("Error attempting to export your library.", "Error exporting", ex);
}
}
#endregion
@@ -396,24 +483,6 @@ namespace LibationWinForms
private void accountsToolStripMenuItem_Click(object sender, EventArgs e) => new AccountsDialog(this).ShowDialog();
private void basicSettingsToolStripMenuItem_Click(object sender, EventArgs e) => new SettingsDialog().ShowDialog();
private void advancedSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
var oldLocation = Configuration.Instance.LibationFiles;
new LibationFilesDialog().ShowDialog();
// no change
if (System.IO.Path.GetFullPath(oldLocation).EqualsInsensitive(System.IO.Path.GetFullPath(Configuration.Instance.LibationFiles)))
return;
MessageBox.Show(
"You have changed a file path important for this program. All files will remain in their original location; nothing will be moved. Libation must be restarted so these changes are handled correctly.",
"Closing Libation",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
Application.Exit();
Environment.Exit(0);
}
#endregion
}
#endregion
}
}

View File

@@ -1,64 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LibationWinForms.Dialogs;
namespace LibationWinForms
{
public static class MessageBoxAlertAdmin
{
/// <summary>
/// Logs error. Displays a message box dialog with specified text and caption.
/// </summary>
/// <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>
/// <returns>One of the System.Windows.Forms.DialogResult values.</returns>
public static System.Windows.Forms.DialogResult Show(string text, string caption, Exception exception)
{
Serilog.Log.Logger.Error(exception, "Alert admin error: {@DebugText}", new { text, caption });
using var form = new MessageBoxAlertAdminDialog(text, caption, exception);
return form.ShowDialog();
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Windows.Forms;
using Dinah.Core.Logging;
using Serilog;
namespace LibationWinForms
{
public static class MessageBoxVerboseLoggingWarning
{
public static void ShowIfTrue()
{
// when turning on debug (and especially Verbose) to share logs, some privacy settings may not be obscured
if (Log.Logger.IsVerboseEnabled())
MessageBox.Show(@"
Warning: verbose logging is enabled.
This should be used for debugging only. It creates many
more logs and debug files, neither of which are as
strictly anonomous.
When you are finished debugging, it's highly recommended
to set your debug MinimumLevel to Information and restart
Libation.
".Trim(), "Verbose logging enabled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Windows.Forms;
using ApplicationServices;
using DataLayer;
using Dinah.Core;
using Dinah.Core.Collections.Generic;
using Dinah.Core.DataBinding;
using Dinah.Core.Windows.Forms;
@@ -178,7 +179,7 @@ namespace LibationWinForms
if (FileManager.AudibleFileStorage.Audio.Exists(productId))
{
var filePath = FileManager.AudibleFileStorage.Audio.GetPath(productId);
System.Diagnostics.Process.Start("explorer.exe", $"/select, \"{filePath}\"");
Go.To.File(filePath);
return;
}

View File

@@ -37,7 +37,7 @@
* Powerful advanced search built on the Lucene search engine
* Customizable saved filters for common searches
* Open source
* Tested on US Audible only. Should theoretically also work for Canada, UK, Germany, France, and Australia
* Supports most regions: US, UK, Canada, Germany, France, Australia, Japan, India, and Spain
<a name="theBad"/>