Handle and notify users of invalid account settings file
This commit is contained in:
parent
b36e110b49
commit
ac036f65f1
@ -5,19 +5,58 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace AudibleUtilities
|
||||
{
|
||||
public class AccountSettingsLoadErrorEventArgs : ErrorEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a new, empty <see cref="AccountsSettings"/> file if true, otherwise throw
|
||||
/// </summary>
|
||||
public bool Handled { get; set; }
|
||||
/// <summary>
|
||||
/// The file path of the AccountsSettings.json file
|
||||
/// </summary>
|
||||
public string SettingsFilePath { get; }
|
||||
|
||||
public AccountSettingsLoadErrorEventArgs(string path, Exception exception)
|
||||
: base(exception)
|
||||
{
|
||||
SettingsFilePath = path;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AudibleApiStorage
|
||||
{
|
||||
public static string AccountsSettingsFile => Path.Combine(Configuration.Instance.LibationFiles, "AccountsSettings.json");
|
||||
|
||||
public static event EventHandler<AccountSettingsLoadErrorEventArgs> LoadError;
|
||||
|
||||
public static void EnsureAccountsSettingsFileExists()
|
||||
{
|
||||
// saves. BEWARE: this will overwrite an existing file
|
||||
if (!File.Exists(AccountsSettingsFile))
|
||||
_ = new AccountsSettingsPersister(new AccountsSettings(), AccountsSettingsFile);
|
||||
{
|
||||
//Save the JSON file manually so that AccountsSettingsPersister.Saving and AccountsSettingsPersister.Saved
|
||||
//are not fired. There's no need to fire those events on an empty AccountsSettings file.
|
||||
var accountSerializerSettings = AudibleApi.Authorization.Identity.GetJsonSerializerSettings();
|
||||
File.WriteAllText(AccountsSettingsFile, JsonConvert.SerializeObject(new AccountsSettings(), Formatting.Indented, accountSerializerSettings));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>If you use this, be a good citizen and DISPOSE of it</summary>
|
||||
public static AccountsSettingsPersister GetAccountsSettingsPersister() => new AccountsSettingsPersister(AccountsSettingsFile);
|
||||
public static AccountsSettingsPersister GetAccountsSettingsPersister()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new AccountsSettingsPersister(AccountsSettingsFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var args = new AccountSettingsLoadErrorEventArgs(AccountsSettingsFile, ex);
|
||||
LoadError?.Invoke(null, args);
|
||||
if (args.Handled)
|
||||
return GetAccountsSettingsPersister();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetIdentityTokensJsonPath(this Account account)
|
||||
=> GetIdentityTokensJsonPath(account.AccountId, account.Locale?.Name);
|
||||
|
||||
@ -157,7 +157,7 @@ namespace FileManager
|
||||
/// <param name="extension">File extension override to use for <paramref name="destination"/></param>
|
||||
/// <param name="overwrite">If <c>false</c> and <paramref name="destination"/> exists, append " (n)" to filename and try again.</param>
|
||||
/// <returns>The actual destination filename</returns>
|
||||
public static string SaferMoveToValidPath(
|
||||
public static LongPath SaferMoveToValidPath(
|
||||
LongPath source,
|
||||
LongPath destination,
|
||||
ReplacementCharacters replacements,
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
using AudibleUtilities;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Threading;
|
||||
using DataLayer;
|
||||
using FileManager;
|
||||
using LibationAvalonia.ViewModels;
|
||||
using LibationFileManager;
|
||||
using LibationUiBase.GridView;
|
||||
@ -18,6 +21,7 @@ namespace LibationAvalonia.Views
|
||||
{
|
||||
DataContext = new MainVM(this);
|
||||
|
||||
AudibleApiStorage.LoadError += AudibleApiStorage_LoadError;
|
||||
InitializeComponent();
|
||||
Configure_Upgrade();
|
||||
|
||||
@ -34,6 +38,62 @@ namespace LibationAvalonia.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void AudibleApiStorage_LoadError(object sender, AccountSettingsLoadErrorEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
//Backup AccountSettings.json and create a new, empty file.
|
||||
var backupFile =
|
||||
FileUtility.SaferMoveToValidPath(
|
||||
e.SettingsFilePath,
|
||||
e.SettingsFilePath,
|
||||
ReplacementCharacters.Barebones,
|
||||
"bak");
|
||||
AudibleApiStorage.EnsureAccountsSettingsFileExists();
|
||||
e.Handled = true;
|
||||
|
||||
showAccountSettingsRecoveredMessage(backupFile);
|
||||
}
|
||||
catch
|
||||
{
|
||||
showAccountSettingsUnrecoveredMessage();
|
||||
}
|
||||
|
||||
async void showAccountSettingsRecoveredMessage(LongPath backupFile)
|
||||
=> await MessageBox.Show(this, $"""
|
||||
Libation could not load your account settings, so it had created a new, empty account settings file.
|
||||
|
||||
You will need to re-add you Audible account(s) before scanning or downloading.
|
||||
|
||||
The old account settings file has been archived at '{backupFile.PathWithoutPrefix}'
|
||||
|
||||
{e.GetException().ToString()}
|
||||
""",
|
||||
"Error Loading Account Settings",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
|
||||
void showAccountSettingsUnrecoveredMessage()
|
||||
{
|
||||
var messageBoxWindow = MessageBox.Show(this, $"""
|
||||
Libation could not load your account settings. The file may be corrupted, but Libation is unable to delete it.
|
||||
|
||||
Please move or delete the account settings file '{e.SettingsFilePath}'
|
||||
|
||||
{e.GetException().ToString()}
|
||||
""",
|
||||
"Error Loading Account Settings",
|
||||
MessageBoxButtons.OK);
|
||||
|
||||
//Force the message box to show synchronously because we're not handling the exception
|
||||
//and libation will crash after the event handler returns
|
||||
var frame = new DispatcherFrame();
|
||||
_ = messageBoxWindow.ContinueWith(static (_, s) => ((DispatcherFrame)s).Continue = false, frame);
|
||||
Dispatcher.UIThread.PushFrame(frame);
|
||||
messageBoxWindow.GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
|
||||
private async void MainWindow_Opened(object sender, EventArgs e)
|
||||
{
|
||||
if (Configuration.Instance.FirstLaunch)
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using ApplicationServices;
|
||||
using AudibleUtilities;
|
||||
using Dinah.Core.WindowsDesktop.Drawing;
|
||||
using FileManager;
|
||||
using LibationFileManager;
|
||||
using LibationUiBase;
|
||||
|
||||
@ -14,6 +12,8 @@ namespace LibationWinForms
|
||||
{
|
||||
private void Configure_NonUI()
|
||||
{
|
||||
AudibleApiStorage.LoadError += AudibleApiStorage_LoadError;
|
||||
|
||||
// init default/placeholder cover art
|
||||
var format = System.Drawing.Imaging.ImageFormat.Jpeg;
|
||||
PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format));
|
||||
@ -36,5 +36,54 @@ namespace LibationWinForms
|
||||
beginBookBackupsToolStripMenuItem_Click();
|
||||
};
|
||||
}
|
||||
|
||||
private void AudibleApiStorage_LoadError(object sender, AccountSettingsLoadErrorEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
//Backup AccountSettings.json and create a new, empty file.
|
||||
var backupFile =
|
||||
FileUtility.SaferMoveToValidPath(
|
||||
e.SettingsFilePath,
|
||||
e.SettingsFilePath,
|
||||
ReplacementCharacters.Barebones,
|
||||
"bak");
|
||||
|
||||
AudibleApiStorage.EnsureAccountsSettingsFileExists();
|
||||
e.Handled = true;
|
||||
|
||||
showAccountSettingsRecoveredMessage(backupFile);
|
||||
}
|
||||
catch
|
||||
{
|
||||
showAccountSettingsUnrecoveredMessage();
|
||||
}
|
||||
|
||||
void showAccountSettingsRecoveredMessage(LongPath backupFile)
|
||||
=> MessageBox.Show(this, $"""
|
||||
Libation could not load your account settings, so it had created a new, empty account settings file.
|
||||
|
||||
You will need to re-add you Audible account(s) before scanning or downloading.
|
||||
|
||||
The old account settings file has been archived at '{backupFile.PathWithoutPrefix}'
|
||||
|
||||
{e.GetException().ToString()}
|
||||
""",
|
||||
"Error Loading Account Settings",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
|
||||
void showAccountSettingsUnrecoveredMessage()
|
||||
=> MessageBox.Show(this, $"""
|
||||
Libation could not load your account settings. The file may be corrupted, but Libation is unable to delete it.
|
||||
|
||||
Please move or delete the account settings file '{e.SettingsFilePath}'
|
||||
|
||||
{e.GetException().ToString()}
|
||||
""",
|
||||
"Error Loading Account Settings",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user