mirror of
https://github.com/rmcrackan/Libation.git
synced 2025-12-30 17:38:14 -05:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efca1f9c1d | ||
|
|
ca14db79b9 | ||
|
|
9d00da006c | ||
|
|
b479096fc2 | ||
|
|
ad09d36588 | ||
|
|
1a9c0188a4 | ||
|
|
ca75b55da4 | ||
|
|
285b1e7b45 | ||
|
|
6912a499d0 | ||
|
|
4e70365150 | ||
|
|
811a95aedf | ||
|
|
20971124ab | ||
|
|
fa66a361dc | ||
|
|
61d7f5a5cb | ||
|
|
f8c788297e | ||
|
|
79e5545fd3 | ||
|
|
b4def2e2d6 | ||
|
|
281d615649 | ||
|
|
c2c6a31716 |
@@ -2,6 +2,7 @@
|
||||
using Dinah.Core;
|
||||
using Dinah.Core.Diagnostics;
|
||||
using Dinah.Core.IO;
|
||||
using Dinah.Core.Logging;
|
||||
using Dinah.Core.StepRunner;
|
||||
using System;
|
||||
using System.IO;
|
||||
@@ -39,6 +40,7 @@ namespace AaxDecrypter
|
||||
ArgumentValidator.EnsureNotNullOrWhiteSpace(outFileName, nameof(outFileName));
|
||||
OutputFileName = outFileName;
|
||||
var outDir = Path.GetDirectoryName(OutputFileName);
|
||||
|
||||
if (!Directory.Exists(outDir))
|
||||
throw new ArgumentNullException(nameof(outDir), "Directory does not exist");
|
||||
if (File.Exists(OutputFileName))
|
||||
@@ -51,6 +53,8 @@ namespace AaxDecrypter
|
||||
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 " + (outputFormat == OutputFormat.Mp4a ? "M4b" : "Mp3"),
|
||||
|
||||
@@ -88,8 +88,8 @@ namespace DataLayer
|
||||
Category = category;
|
||||
|
||||
// simple assigns
|
||||
Title = title;
|
||||
Description = description;
|
||||
Title = title.Trim();
|
||||
Description = description.Trim();
|
||||
LengthInMinutes = lengthInMinutes;
|
||||
|
||||
// assigns with biz logic
|
||||
|
||||
@@ -67,9 +67,6 @@ namespace DtoImporterService
|
||||
{
|
||||
var item = importItem.DtoItem;
|
||||
|
||||
//Add any subtitle after the title title.
|
||||
var title = item.Title + (!string.IsNullOrWhiteSpace(item.Subtitle) ? $": {item.Subtitle}" : "");
|
||||
|
||||
// absence of authors is very rare, but possible
|
||||
if (!item.Authors?.Any() ?? true)
|
||||
item.Authors = new[] { new Person { Name = "", Asin = null } };
|
||||
@@ -105,7 +102,7 @@ namespace DtoImporterService
|
||||
|
||||
var book = DbContext.Books.Add(new Book(
|
||||
new AudibleProductId(item.ProductId),
|
||||
title,
|
||||
item.TitleWithSubtitle,
|
||||
item.Description,
|
||||
item.LengthInMinutes,
|
||||
authors,
|
||||
|
||||
@@ -70,12 +70,12 @@ namespace FileLiberator
|
||||
var api = await InternalUtilities.AudibleApiActions.GetApiAsync(libraryBook.Account, libraryBook.Book.Locale);
|
||||
|
||||
var contentLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId);
|
||||
|
||||
|
||||
var aaxcDecryptDlLic = new DownloadLicense
|
||||
(
|
||||
contentLic.ContentMetadata?.ContentUrl?.OfflineUrl,
|
||||
contentLic.Voucher?.Key,
|
||||
contentLic.Voucher?.Iv,
|
||||
contentLic?.ContentMetadata?.ContentUrl?.OfflineUrl,
|
||||
contentLic?.Voucher?.Key,
|
||||
contentLic?.Voucher?.Iv,
|
||||
Resources.UserAgent
|
||||
);
|
||||
|
||||
|
||||
@@ -48,7 +48,11 @@ namespace FileManager
|
||||
|
||||
public object GetObject(string propertyName) => persistentDictionary.GetObject(propertyName);
|
||||
public void SetObject(string propertyName, object newValue) => persistentDictionary.SetNonString(propertyName, newValue);
|
||||
public void SetWithJsonPath(string jsonPath, string propertyName, string newValue, bool suppressLogging = false) => persistentDictionary.SetWithJsonPath(jsonPath, propertyName, newValue, suppressLogging);
|
||||
|
||||
/// <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");
|
||||
|
||||
@@ -65,6 +69,38 @@ namespace FileManager
|
||||
|
||||
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
|
||||
{
|
||||
@@ -187,7 +223,12 @@ namespace FileManager
|
||||
}
|
||||
set
|
||||
{
|
||||
persistentDictionary.SetWithJsonPath("Serilog", "MinimumLevel", value.ToString());
|
||||
var valueWasChanged = persistentDictionary.SetWithJsonPath("Serilog", "MinimumLevel", value.ToString());
|
||||
if (!valueWasChanged)
|
||||
{
|
||||
Log.Logger.Information("LogLevel.set attempt. No change");
|
||||
return;
|
||||
}
|
||||
|
||||
configuration.Reload();
|
||||
|
||||
@@ -231,8 +272,9 @@ namespace FileManager
|
||||
// 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");
|
||||
SetWithJsonPath("Serilog.WriteTo[1].Args", "path", logPath, true);
|
||||
configuration?.Reload();
|
||||
bool settingWasChanged = SetWithJsonPath("Serilog.WriteTo[1].Args", "path", logPath, true);
|
||||
if (settingWasChanged)
|
||||
configuration?.Reload();
|
||||
|
||||
return libationFilesPathCache;
|
||||
}
|
||||
@@ -275,19 +317,8 @@ namespace FileManager
|
||||
return valueFinal;
|
||||
}
|
||||
|
||||
public bool TrySetLibationFiles(string directory)
|
||||
public void SetLibationFiles(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);
|
||||
@@ -297,7 +328,7 @@ namespace FileManager
|
||||
|
||||
var endingContents = JsonConvert.SerializeObject(jObj, Formatting.Indented);
|
||||
if (startingContents == endingContents)
|
||||
return true;
|
||||
return;
|
||||
|
||||
// now it's set in the file again but no settings have moved yet
|
||||
File.WriteAllText(APPSETTINGS_JSON, endingContents);
|
||||
@@ -307,13 +338,6 @@ namespace FileManager
|
||||
Log.Logger.Information("Libation files changed {@DebugInfo}", new { APPSETTINGS_JSON, LIBATION_FILES_KEY, directory });
|
||||
}
|
||||
catch { }
|
||||
|
||||
//// attempting this will try to change the settings file which has not yet been moved
|
||||
//// after this is fixed, can remove it from Program.configureLogging()
|
||||
// var logPath = Path.Combine(LibationFiles, "Log.log");
|
||||
// SetWithJsonPath("Serilog.WriteTo[1].Args", "path", logPath, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -142,33 +142,44 @@ namespace FileManager
|
||||
catch { }
|
||||
}
|
||||
|
||||
public void SetWithJsonPath(string jsonPath, string propertyName, string newValue, bool suppressLogging = false)
|
||||
/// <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)
|
||||
{
|
||||
if (IsReadOnly)
|
||||
return;
|
||||
return false;
|
||||
|
||||
var path = $"{jsonPath}.{propertyName}";
|
||||
|
||||
{
|
||||
// only do this check in string cache, NOT object cache
|
||||
if (stringCache.ContainsKey(path) && stringCache[path] == newValue)
|
||||
return;
|
||||
return false;
|
||||
|
||||
// set cache
|
||||
stringCache[path] = newValue;
|
||||
}
|
||||
|
||||
lock (locker)
|
||||
try
|
||||
{
|
||||
var jObject = readFile();
|
||||
var token = jObject.SelectToken(jsonPath);
|
||||
var oldValue = token.Value<string>(propertyName);
|
||||
lock (locker)
|
||||
{
|
||||
var jObject = readFile();
|
||||
var token = jObject.SelectToken(jsonPath);
|
||||
if (token is null || token[propertyName] is null)
|
||||
return false;
|
||||
|
||||
if (oldValue == newValue)
|
||||
return;
|
||||
var oldValue = token.Value<string>(propertyName);
|
||||
if (oldValue == newValue)
|
||||
return false;
|
||||
|
||||
token[propertyName] = newValue;
|
||||
File.WriteAllText(Filepath, JsonConvert.SerializeObject(jObject, Formatting.Indented));
|
||||
token[propertyName] = newValue;
|
||||
File.WriteAllText(Filepath, JsonConvert.SerializeObject(jObject, Formatting.Indented));
|
||||
}
|
||||
}
|
||||
catch (Exception exDebug)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!suppressLogging)
|
||||
@@ -180,6 +191,8 @@ namespace FileManager
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string formatValueForLog(string value)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<!-- <PublishSingleFile>true</PublishSingleFile> -->
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
||||
<Version>5.3.2.1</Version>
|
||||
<Version>5.3.9.2</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace LibationLauncher
|
||||
// check for existing settigns in default location
|
||||
var defaultSettingsFile = Path.Combine(defaultLibationFilesDir, "Settings.json");
|
||||
if (Configuration.SettingsFileIsValid(defaultSettingsFile))
|
||||
config.TrySetLibationFiles(defaultLibationFilesDir);
|
||||
config.SetLibationFiles(defaultLibationFilesDir);
|
||||
|
||||
if (config.LibationSettingsAreValid)
|
||||
return;
|
||||
@@ -94,7 +94,7 @@ namespace LibationLauncher
|
||||
}
|
||||
|
||||
if (setupDialog.IsNewUser)
|
||||
config.TrySetLibationFiles(defaultLibationFilesDir);
|
||||
config.SetLibationFiles(defaultLibationFilesDir);
|
||||
else if (setupDialog.IsReturningUser)
|
||||
{
|
||||
var libationFilesDialog = new LibationFilesDialog();
|
||||
@@ -105,7 +105,7 @@ namespace LibationLauncher
|
||||
return;
|
||||
}
|
||||
|
||||
config.TrySetLibationFiles(libationFilesDialog.SelectedDirectory);
|
||||
config.SetLibationFiles(libationFilesDialog.SelectedDirectory);
|
||||
if (config.LibationSettingsAreValid)
|
||||
return;
|
||||
|
||||
@@ -328,19 +328,7 @@ namespace LibationLauncher
|
||||
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.
|
||||
|
||||
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);
|
||||
MessageBoxVerboseLoggingWarning.ShowIfTrue();
|
||||
}
|
||||
|
||||
private static void checkForUpdate(Configuration config)
|
||||
@@ -351,7 +339,7 @@ Libation.
|
||||
try
|
||||
{
|
||||
// timed out
|
||||
var latest = getLatestRelease(TimeSpan.FromSeconds(30));
|
||||
var latest = getLatestRelease(TimeSpan.FromSeconds(10));
|
||||
if (latest is null)
|
||||
return;
|
||||
|
||||
@@ -388,6 +376,11 @@ Libation.
|
||||
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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +94,16 @@ namespace LibationWinForms.Dialogs
|
||||
|
||||
config.Books = newBooks;
|
||||
|
||||
config.LogLevel = (Serilog.Events.LogEventLevel)loggingLevelCb.SelectedItem;
|
||||
{
|
||||
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;
|
||||
|
||||
17
LibationWinForms/Form1.Designer.cs
generated
17
LibationWinForms/Form1.Designer.cs
generated
@@ -51,7 +51,6 @@
|
||||
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();
|
||||
@@ -232,8 +231,7 @@
|
||||
//
|
||||
this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.accountsToolStripMenuItem,
|
||||
this.basicSettingsToolStripMenuItem,
|
||||
this.advancedSettingsToolStripMenuItem});
|
||||
this.basicSettingsToolStripMenuItem});
|
||||
this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
|
||||
this.settingsToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
|
||||
this.settingsToolStripMenuItem.Text = "&Settings";
|
||||
@@ -241,24 +239,17 @@
|
||||
// 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.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 = "&Move settings files...";
|
||||
this.advancedSettingsToolStripMenuItem.Click += new System.EventHandler(this.advancedSettingsToolStripMenuItem_Click);
|
||||
//
|
||||
// statusStrip1
|
||||
//
|
||||
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
@@ -325,6 +316,7 @@
|
||||
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();
|
||||
@@ -359,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;
|
||||
|
||||
@@ -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)
|
||||
@@ -395,31 +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 libationFilesDialog = new LibationFilesDialog();
|
||||
if (libationFilesDialog.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
|
||||
// no change
|
||||
if (System.IO.Path.GetFullPath(libationFilesDialog.SelectedDirectory).EqualsInsensitive(System.IO.Path.GetFullPath(Configuration.Instance.LibationFiles)))
|
||||
return;
|
||||
|
||||
if (!Configuration.Instance.TrySetLibationFiles(libationFilesDialog.SelectedDirectory))
|
||||
{
|
||||
MessageBox.Show("Not saving change to Libation Files location. This folder does not exist:\r\n" + libationFilesDialog.SelectedDirectory, "Error saving change", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
27
LibationWinForms/MessageBoxWarnIfVerboseLogging.cs
Normal file
27
LibationWinForms/MessageBoxWarnIfVerboseLogging.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user