Libation Runs on MacOS

This commit is contained in:
Michael Bucari-Tovo 2022-07-30 16:09:31 -06:00
parent 8020ded642
commit 0bfa609058
30 changed files with 147 additions and 171 deletions

View File

@ -5,10 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AudibleApi" Version="4.5.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\audible api\AudibleApi\AudibleApi\AudibleApi.csproj" />
<ProjectReference Include="..\LibationFileManager\LibationFileManager.csproj" />
</ItemGroup>

View File

@ -115,7 +115,7 @@ namespace LibationAvalonia
base.OnFrameworkInitializationCompleted();
}
private void Setup_Closing(object sender, System.ComponentModel.CancelEventArgs e)
private async void Setup_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
var setupDialog = sender as SetupDialog;
var desktop = ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
@ -128,9 +128,9 @@ namespace LibationAvalonia
if ((!setupDialog.IsNewUser
&& !setupDialog.IsReturningUser) ||
!RunInstall(setupDialog))
!await RunInstall(setupDialog))
{
CancelInstallation();
await CancelInstallation();
return;
}
@ -138,7 +138,7 @@ namespace LibationAvalonia
// most migrations go in here
AppScaffolding.LibationScaffolding.RunPostConfigMigrations(setupDialog.Config);
MessageBox.VerboseLoggingWarning_ShowIfTrue();
await MessageBox.VerboseLoggingWarning_ShowIfTrue();
#if !DEBUG
//AutoUpdater.NET only works for WinForms or WPF application projects.
@ -154,11 +154,11 @@ namespace LibationAvalonia
var body = "An unrecoverable error occurred. Since this error happened before logging could be initialized, this error can not be written to the log file.";
try
{
MessageBox.ShowAdminAlert(null, body, title, ex);
await MessageBox.ShowAdminAlert(null, body, title, ex);
}
catch
{
MessageBox.Show($"{body}\r\n\r\n{ex.Message}\r\n\r\n{ex.StackTrace}", title, MessageBoxButtons.OK, MessageBoxIcon.Error);
await MessageBox.Show($"{body}\r\n\r\n{ex.Message}\r\n\r\n{ex.StackTrace}", title, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return;
}
@ -168,7 +168,7 @@ namespace LibationAvalonia
ShowMainWindow(desktop);
}
private static bool RunInstall(SetupDialog setupDialog)
private static async Task<bool> RunInstall(SetupDialog setupDialog)
{
var config = setupDialog.Config;
@ -181,7 +181,7 @@ namespace LibationAvalonia
var libationFilesDialog = new LibationFilesDialog();
if (libationFilesDialog.ShowDialogSynchronously<DialogResult>(setupDialog) != DialogResult.OK)
if (await libationFilesDialog.ShowDialog<DialogResult>(setupDialog) != DialogResult.OK)
return false;
config.SetLibationFiles(libationFilesDialog.SelectedDirectory);
@ -189,7 +189,7 @@ namespace LibationAvalonia
return true;
// path did not result in valid settings
var continueResult = MessageBox.Show(
var continueResult = await 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,
@ -204,13 +204,13 @@ namespace LibationAvalonia
config.Books ??= Path.Combine(Configuration.UserProfile, "Books");
AppScaffolding.LibationScaffolding.PopulateMissingConfigValues(config);
return new SettingsDialog().ShowDialogSynchronously<DialogResult>(setupDialog) == DialogResult.OK
return await new SettingsDialog().ShowDialog<DialogResult>(setupDialog) == DialogResult.OK
&& config.LibationSettingsAreValid;
}
static void CancelInstallation()
static async Task CancelInstallation()
{
MessageBox.Show("Initial set up cancelled.", "Cancelled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
await MessageBox.Show("Initial set up cancelled.", "Cancelled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
Environment.Exit(0);
}

View File

@ -6,25 +6,5 @@ namespace Avalonia.Threading
{
internal static class AvaloniaThreadUtils
{
public static TResult Invoke<TResult>(this Dispatcher dispatcher, Func<TResult> function, DispatcherPriority dispatcherPriority = DispatcherPriority.Normal)
=> WaitOnDispatcherAndGetResult(dispatcher.InvokeAsync(function, dispatcherPriority), dispatcher);
public static void Invoke(this Dispatcher dispatcher, Action action, DispatcherPriority dispatcherPriority = DispatcherPriority.Normal)
=> WaitOnDispatcher(dispatcher.InvokeAsync(action, dispatcherPriority), dispatcher);
public static TResult WaitOnDispatcherAndGetResult<TResult>(this Task<TResult> task, Dispatcher dispatcher)
{
using var source = new CancellationTokenSource();
task.ContinueWith(t => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext());
dispatcher.MainLoop(source.Token);
return task.Result;
}
public static void WaitOnDispatcher(this Task task, Dispatcher dispatcher)
{
using var source = new CancellationTokenSource();
task.ContinueWith(t => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext());
dispatcher.MainLoop(source.Token);
}
}
}

View File

@ -17,9 +17,5 @@ namespace LibationAvalonia
return defaultBrush;
}
public static T ShowDialogSynchronously<T>(this Avalonia.Controls.Window window, Avalonia.Controls.Window owner)
{
return window.ShowDialog<T>(owner).WaitOnDispatcherAndGetResult(Dispatcher.UIThread);
}
}
}

View File

@ -136,7 +136,7 @@ namespace LibationAvalonia.Dialogs
if (persister.AccountsSettings.Accounts.Any(a => a.AccountId == account.AccountId && a.IdentityTokens.Locale.Name == account.Locale.Name))
{
MessageBox.Show(this, $"An account with that account id and country already exists.\r\n\r\nAccount ID: {account.AccountId}\r\nCountry: {account.Locale.Name}", "Cannot Add Duplicate Account");
await MessageBox.Show(this, $"An account with that account id and country already exists.\r\n\r\nAccount ID: {account.AccountId}\r\nCountry: {account.Locale.Name}", "Cannot Add Duplicate Account");
return;
}
@ -146,7 +146,7 @@ namespace LibationAvalonia.Dialogs
}
catch (Exception ex)
{
MessageBox.ShowAdminAlert(
await MessageBox.ShowAdminAlert(
this,
$"An error occurred while importing an account from:\r\n{filePath[0]}\r\n\r\nIs the file encrypted?",
"Error Importing Account",
@ -160,11 +160,11 @@ namespace LibationAvalonia.Dialogs
Export(acc);
}
protected override void SaveAndClose()
protected override async Task SaveAndCloseAsync()
{
try
{
if (!inputIsValid())
if (!await inputIsValid())
return;
// without transaction, accounts persister will write ANY EDIT immediately to file
@ -178,7 +178,7 @@ namespace LibationAvalonia.Dialogs
}
catch (Exception ex)
{
MessageBox.ShowAdminAlert(this, "Error attempting to save accounts", "Error saving accounts", ex);
await MessageBox.ShowAdminAlert(this, "Error attempting to save accounts", "Error saving accounts", ex);
}
}
@ -221,7 +221,7 @@ namespace LibationAvalonia.Dialogs
: dto.AccountName.Trim();
}
}
private bool inputIsValid()
private async Task<bool> inputIsValid()
{
foreach (var dto in Accounts.ToList())
{
@ -233,13 +233,13 @@ namespace LibationAvalonia.Dialogs
if (string.IsNullOrWhiteSpace(dto.AccountId))
{
MessageBox.Show(this, "Account id cannot be blank. Please enter an account id for all accounts.", "Blank account", MessageBoxButtons.OK, MessageBoxIcon.Error);
await MessageBox.Show(this, "Account id cannot be blank. Please enter an account id for all accounts.", "Blank account", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
if (string.IsNullOrWhiteSpace(dto.SelectedLocale?.Name))
{
MessageBox.Show(this, "Please select a locale (i.e.: country or region) for all accounts.", "Blank region", MessageBoxButtons.OK, MessageBoxIcon.Error);
await MessageBox.Show(this, "Please select a locale (i.e.: country or region) for all accounts.", "Blank region", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
@ -259,7 +259,7 @@ namespace LibationAvalonia.Dialogs
if (account.IdentityTokens?.IsValid != true)
{
MessageBox.Show(this, "This account hasn't been authenticated yet. First scan your library to log into your account, then try exporting again.", "Account Not Authenticated");
await MessageBox.Show(this, "This account hasn't been authenticated yet. First scan your library to log into your account, then try exporting again.", "Account Not Authenticated");
return;
}
@ -282,11 +282,11 @@ namespace LibationAvalonia.Dialogs
File.WriteAllText(fileName, jsonText);
MessageBox.Show(this, $"Successfully exported {account.AccountName} to\r\n\r\n{fileName}", "Success!");
await MessageBox.Show(this, $"Successfully exported {account.AccountName} to\r\n\r\n{fileName}", "Success!");
}
catch (Exception ex)
{
MessageBox.ShowAdminAlert(
await MessageBox.ShowAdminAlert(
this,
$"An error occurred while exporting account:\r\n{account.AccountName}",
"Error Exporting Account",

View File

@ -64,7 +64,7 @@ namespace LibationAvalonia.Dialogs
}
protected override async Task SaveAndCloseAsync()
{
if (!_viewModel.Validate())
if (!await _viewModel.Validate())
return;
TemplateText = _viewModel.workingTemplateText;
@ -115,7 +115,7 @@ namespace LibationAvalonia.Dialogs
public void resetTextBox(string value) => workingTemplateText = value;
public bool Validate()
public async Task<bool> Validate()
{
if (template.IsValid(workingTemplateText))
return true;
@ -123,7 +123,7 @@ namespace LibationAvalonia.Dialogs
.GetErrors(workingTemplateText)
.Select(err => $"- {err}")
.Aggregate((a, b) => $"{a}\r\n{b}");
MessageBox.Show($"This template text is not valid. Errors:\r\n{errors}", "Invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
await MessageBox.Show($"This template text is not valid. Errors:\r\n{errors}", "Invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}

View File

@ -67,7 +67,7 @@ namespace LibationAvalonia.Dialogs
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, $"Failed to save picture to {fileName}");
MessageBox.Show(this, $"An error was encountered while trying to save the picture\r\n\r\n{ex.Message}", "Failed to save picture", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
await MessageBox.Show(this, $"An error was encountered while trying to save the picture\r\n\r\n{ex.Message}", "Failed to save picture", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
}

View File

@ -33,14 +33,14 @@ namespace LibationAvalonia.Dialogs
DataContext = dirSelectOptions = new();
}
public void SaveButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
public async void SaveButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
var libationDir = dirSelectOptions.Directory;
if (!System.IO.Directory.Exists(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, saveAndRestorePosition: false);
await 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, saveAndRestorePosition: false);
return;
}

View File

@ -9,12 +9,12 @@ namespace LibationAvalonia.Dialogs.Login
{
/// <returns>True if ShowDialog's DialogResult == OK</returns>
protected static bool ShowDialog(DialogWindow dialog)
protected static async Task<bool> ShowDialog(DialogWindow dialog)
{
if (Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
return false;
var result = dialog.ShowDialogSynchronously<DialogResult>(desktop.MainWindow);
var result = await dialog.ShowDialog<DialogResult>(desktop.MainWindow);
Serilog.Log.Logger.Debug("{@DebugInfo}", new { DialogResult = result });
return result == DialogResult.OK;
}

View File

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using AudibleApi;
using AudibleUtilities;
@ -13,43 +14,43 @@ namespace LibationAvalonia.Dialogs.Login
_account = Dinah.Core.ArgumentValidator.EnsureNotNull(account, nameof(account));
}
public string Get2faCode()
public async Task<string> Get2faCodeAsync()
{
var dialog = new _2faCodeDialog();
if (ShowDialog(dialog))
if (await ShowDialog(dialog))
return dialog.Code;
return null;
}
public string GetCaptchaAnswer(byte[] captchaImage)
public async Task<string> GetCaptchaAnswerAsync(byte[] captchaImage)
{
var dialog = new CaptchaDialog(captchaImage);
if (ShowDialog(dialog))
if (await ShowDialog(dialog))
return dialog.Answer;
return null;
}
public (string name, string value) GetMfaChoice(MfaConfig mfaConfig)
public async Task<(string name, string value)> GetMfaChoiceAsync(MfaConfig mfaConfig)
{
var dialog = new MfaDialog(mfaConfig);
if (ShowDialog(dialog))
if (await ShowDialog(dialog))
return (dialog.SelectedName, dialog.SelectedValue);
return (null, null);
}
public (string email, string password) GetLogin()
public async Task<(string email, string password)> GetLoginAsync()
{
var dialog = new LoginCallbackDialog(_account);
if (ShowDialog(dialog))
if (await ShowDialog(dialog))
return (_account.AccountId, dialog.Password);
return (null, null);
}
public void ShowApprovalNeeded()
public async Task ShowApprovalNeededAsync()
{
var dialog = new ApprovalNeededDialog();
ShowDialog(dialog);
await ShowDialog(dialog);
}
}
}

View File

@ -20,11 +20,11 @@ namespace LibationAvalonia.Dialogs.Login
LoginCallback = new AvaloniaLoginCallback(_account);
}
public ChoiceOut Start(ChoiceIn choiceIn)
public async Task<ChoiceOut> StartAsync(ChoiceIn choiceIn)
{
var dialog = new LoginChoiceEagerDialog(_account);
if (!ShowDialog(dialog))
if (!await ShowDialog(dialog))
return null;
@ -33,15 +33,16 @@ namespace LibationAvalonia.Dialogs.Login
case LoginMethod.Api:
return ChoiceOut.WithApi(dialog.Account.AccountId, dialog.Password);
case LoginMethod.External:
{
var externalDialog = new LoginExternalDialog(_account, choiceIn.LoginUrl);
return ShowDialog(externalDialog)
? ChoiceOut.External(externalDialog.ResponseUrl)
: null;
}
{
var externalDialog = new LoginExternalDialog(_account, choiceIn.LoginUrl);
return await ShowDialog(externalDialog)
? ChoiceOut.External(externalDialog.ResponseUrl)
: null;
}
default:
throw new Exception($"Unknown {nameof(LoginMethod)} value");
}
}
}
}

View File

@ -51,7 +51,7 @@ namespace LibationAvalonia.Dialogs.Login
Serilog.Log.Logger.Information("Submit button clicked: {@DebugInfo}", new { ResponseUrl });
if (!Uri.TryCreate(ResponseUrl, UriKind.Absolute, out var result))
{
MessageBox.Show("Invalid response URL");
await MessageBox.Show("Invalid response URL");
return;
}
await base.SaveAndCloseAsync();

View File

@ -82,7 +82,7 @@ namespace LibationAvalonia.Dialogs.Login
});
if (selected is null)
{
MessageBox.Show("No MFA option selected", "None selected", MessageBoxButtons.OK, MessageBoxIcon.Error);
await MessageBox.Show("No MFA option selected", "None selected", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}

View File

@ -28,7 +28,7 @@ namespace LibationAvalonia.Dialogs
DataContext = this;
}
private void GoToGithub_Tapped(object sender, Avalonia.Interactivity.RoutedEventArgs e)
private async void GoToGithub_Tapped(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
var url = "https://github.com/rmcrackan/Libation/issues";
try
@ -37,11 +37,11 @@ namespace LibationAvalonia.Dialogs
}
catch
{
MessageBox.Show($"Error opening url\r\n{url}", "Error opening url", MessageBoxButtons.OK, MessageBoxIcon.Error);
await MessageBox.Show($"Error opening url\r\n{url}", "Error opening url", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void GoToLogs_Tapped(object sender, Avalonia.Interactivity.RoutedEventArgs e)
private async void GoToLogs_Tapped(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
LongPath dir = "";
try
@ -56,7 +56,7 @@ namespace LibationAvalonia.Dialogs
}
catch
{
MessageBox.Show($"Error opening folder\r\n{dir}", "Error opening folder", MessageBoxButtons.OK, MessageBoxIcon.Error);
await MessageBox.Show($"Error opening folder\r\n{dir}", "Error opening folder", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}

View File

@ -33,10 +33,10 @@ namespace LibationAvalonia.Dialogs
protected override async Task SaveAndCloseAsync()
{
if (!settingsDisp.SaveSettings(config))
if (!await settingsDisp.SaveSettingsAsync(config))
return;
MessageBox.VerboseLoggingWarning_ShowIfTrue();
await MessageBox.VerboseLoggingWarning_ShowIfTrue();
await base.SaveAndCloseAsync();
}
@ -97,7 +97,7 @@ namespace LibationAvalonia.Dialogs
internal interface ISettingsDisplay
{
void LoadSettings(Configuration config);
bool SaveSettings(Configuration config);
Task<bool> SaveSettingsAsync(Configuration config);
}
public class SettingsPages : ISettingsDisplay
@ -120,12 +120,12 @@ namespace LibationAvalonia.Dialogs
AudioSettings = new(config);
}
public bool SaveSettings(Configuration config)
public async Task<bool> SaveSettingsAsync(Configuration config)
{
var result = ImportantSettings.SaveSettings(config);
result &= ImportSettings.SaveSettings(config);
result &= DownloadDecryptSettings.SaveSettings(config);
result &= AudioSettings.SaveSettings(config);
var result = await ImportantSettings.SaveSettingsAsync(config);
result &= await ImportSettings.SaveSettingsAsync(config);
result &= await DownloadDecryptSettings.SaveSettingsAsync(config);
result &= await AudioSettings.SaveSettingsAsync(config);
return result;
}
@ -146,13 +146,13 @@ namespace LibationAvalonia.Dialogs
BetaOptIn = config.BetaOptIn;
}
public bool SaveSettings(Configuration config)
public async Task<bool> SaveSettingsAsync(Configuration config)
{
#region validation
if (string.IsNullOrWhiteSpace(BooksDirectory))
{
MessageBox.Show("Cannot set Books Location to blank", "Location is blank", MessageBoxButtons.OK, MessageBoxIcon.Error);
await MessageBox.Show("Cannot set Books Location to blank", "Location is blank", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
@ -204,14 +204,14 @@ namespace LibationAvalonia.Dialogs
AutoDownloadEpisodes = config.AutoDownloadEpisodes;
}
public bool SaveSettings(Configuration config)
public Task<bool> SaveSettingsAsync(Configuration config)
{
config.AutoScan = AutoScan;
config.ShowImportedStats = ShowImportedStats;
config.ImportEpisodes = ImportEpisodes;
config.DownloadEpisodes = DownloadEpisodes;
config.AutoDownloadEpisodes = AutoDownloadEpisodes;
return true;
return Task.FromResult(true);
}
public string AutoScanText { get; } = Configuration.GetDescription(nameof(Configuration.AutoScan));
@ -259,25 +259,25 @@ namespace LibationAvalonia.Dialogs
: Configuration.GetKnownDirectory(config.InProgress);
}
public bool SaveSettings(Configuration config)
public async Task<bool> SaveSettingsAsync(Configuration config)
{
static void validationError(string text, string caption)
static Task validationError(string text, string caption)
=> MessageBox.Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
// these 3 should do nothing. Configuration will only init these with a valid value. EditTemplateDialog ensures valid before returning
if (!Templates.Folder.IsValid(FolderTemplate))
{
validationError($"Not saving change to folder naming template. Invalid format.", "Invalid folder template");
await validationError($"Not saving change to folder naming template. Invalid format.", "Invalid folder template");
return false;
}
if (!Templates.File.IsValid(FileTemplate))
{
validationError($"Not saving change to file naming template. Invalid format.", "Invalid file template");
await validationError($"Not saving change to file naming template. Invalid format.", "Invalid file template");
return false;
}
if (!Templates.ChapterFile.IsValid(ChapterFileTemplate))
{
validationError($"Not saving change to chapter file naming template. Invalid format.", "Invalid chapter file template");
await validationError($"Not saving change to chapter file naming template. Invalid format.", "Invalid chapter file template");
return false;
}
@ -405,7 +405,7 @@ namespace LibationAvalonia.Dialogs
LameVBRQuality = config.LameVBRQuality;
}
public bool SaveSettings(Configuration config)
public Task<bool> SaveSettingsAsync(Configuration config)
{
config.CreateCueSheet = CreateCueSheet;
config.AllowLibationFixup = AllowLibationFixup;
@ -424,7 +424,7 @@ namespace LibationAvalonia.Dialogs
config.LameBitrate = LameBitrate;
config.LameVBRQuality = LameVBRQuality;
return true;
return Task.FromResult(true);
}
public string CreateCueSheetText { get; } = Configuration.GetDescription(nameof(Configuration.CreateCueSheet));

View File

@ -81,8 +81,6 @@
<None Remove="Assets\SEGOEUI.TTF" />
<None Remove="Assets\up.png" />
<None Remove="Assets\WINGDING.TTF" />
<None Remove="MessageBox.cs~RF105afb8d.TMP" />
<None Remove="Views\MainWindow\MainWindow.Export.axaml.cs~RF10732d95.TMP" />
</ItemGroup>
<ItemGroup>

View File

@ -62,34 +62,34 @@ namespace LibationAvalonia
public class MessageBox
{
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
public static Task<DialogResult> Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
=> ShowCoreAsync(null, text, caption, buttons, icon, defaultButton);
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, bool saveAndRestorePosition = true)
public static Task<DialogResult> Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, bool saveAndRestorePosition = true)
=> ShowCoreAsync(null, text, caption, buttons, icon, MessageBoxDefaultButton.Button1, saveAndRestorePosition);
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons)
public static Task<DialogResult> Show(string text, string caption, MessageBoxButtons buttons)
=> ShowCoreAsync(null, text, caption, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
public static DialogResult Show(string text, string caption)
public static Task<DialogResult> Show(string text, string caption)
=> ShowCoreAsync(null, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
public static DialogResult Show(string text)
public static Task<DialogResult> Show(string text)
=> ShowCoreAsync(null, text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
public static DialogResult Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
public static Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
=> ShowCoreAsync(owner, text, caption, buttons, icon, defaultButton);
public static DialogResult Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
public static Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
=> ShowCoreAsync(owner, text, caption, buttons, icon, MessageBoxDefaultButton.Button1);
public static DialogResult Show(Window owner, string text, string caption, MessageBoxButtons buttons)
public static Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons)
=> ShowCoreAsync(owner, text, caption, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
public static DialogResult Show(Window owner, string text, string caption)
public static Task<DialogResult> Show(Window owner, string text, string caption)
=> ShowCoreAsync(owner, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
public static DialogResult Show(Window owner, string text)
public static Task<DialogResult> Show(Window owner, string text)
=> ShowCoreAsync(owner, text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
public static void VerboseLoggingWarning_ShowIfTrue()
public static async Task VerboseLoggingWarning_ShowIfTrue()
{
// when turning on debug (and especially Verbose) to share logs, some privacy settings may not be obscured
if (Serilog.Log.Logger.IsVerboseEnabled())
Show(@"
await Show(@"
Warning: verbose logging is enabled.
This should be used for debugging only. It creates many
@ -102,7 +102,7 @@ Libation.
".Trim(), "Verbose logging enabled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
public static DialogResult ShowConfirmationDialog(Window owner, IEnumerable<LibraryBook> libraryBooks, string format, string title, MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1)
public static async Task<DialogResult> ShowConfirmationDialog(Window owner, IEnumerable<LibraryBook> libraryBooks, string format, string title, MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1)
{
if (libraryBooks is null || !libraryBooks.Any())
return DialogResult.Cancel;
@ -117,7 +117,7 @@ Libation.
= string.Format(format, $"{thisThese} {count} {bookBooks}")
+ $"\r\n\r\n{titlesAgg}";
return ShowCoreAsync(owner,
return await ShowCoreAsync(owner,
message,
title,
MessageBoxButtons.YesNo,
@ -132,7 +132,7 @@ Libation.
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <param name="exception">Exception to log.</param>
public static void ShowAdminAlert(Window owner, string text, string caption, Exception exception)
public static async Task ShowAdminAlert(Window owner, string text, string caption, Exception exception)
{
// for development and debugging, show me what broke!
if (System.Diagnostics.Debugger.IsAttached)
@ -146,14 +146,14 @@ Libation.
var form = new MessageBoxAlertAdminDialog(text, caption, exception);
DisplayWindow(form, owner);
await DisplayWindow(form, owner);
}
private static DialogResult ShowCoreAsync(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
private static async Task<DialogResult> ShowCoreAsync(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
{
var dialog = Dispatcher.UIThread.Invoke(() => CreateMessageBox(owner, message, caption, buttons, icon, defaultButton, saveAndRestorePosition));
var dialog = await Dispatcher.UIThread.InvokeAsync(() => CreateMessageBox(owner, message, caption, buttons, icon, defaultButton, saveAndRestorePosition));
return DisplayWindow(dialog, owner);
return await DisplayWindow(dialog, owner);
}
private static MessageBoxWindow CreateMessageBox(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
@ -192,13 +192,13 @@ Libation.
dialog.Width = dialog.MinWidth;
return dialog;
}
private static DialogResult DisplayWindow(Window toDisplay, Window owner)
private static async Task<DialogResult> DisplayWindow(Window toDisplay, Window owner)
{
if (owner is null)
{
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
return toDisplay.ShowDialogSynchronously<DialogResult>(desktop.MainWindow);
return await toDisplay.ShowDialog<DialogResult>(desktop.MainWindow);
}
else
{
@ -212,7 +212,7 @@ Libation.
};
window.Show();
var result = toDisplay.ShowDialogSynchronously<DialogResult>(window);
var result = await toDisplay.ShowDialog<DialogResult>(window);
window.Close();
return result;
}
@ -220,7 +220,7 @@ Libation.
}
else
{
return toDisplay.ShowDialogSynchronously<DialogResult>(owner);
return await toDisplay.ShowDialog<DialogResult>(owner);
}
}

View File

@ -14,7 +14,7 @@ namespace LibationAvalonia
{
private static string EXE_DIR = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
static async Task Main()
static void Main()
{
//***********************************************//
// //
@ -47,9 +47,7 @@ namespace LibationAvalonia
App.LibraryTask = Task.Run(() => DbContexts.GetLibrary_Flat_NoTracking(includeParents: true));
}
(await appBuilderTask).SetupWithLifetime(await classicLifetimeTask);
(appBuilderTask.GetAwaiter().GetResult()).SetupWithLifetime(classicLifetimeTask.GetAwaiter().GetResult());
classicLifetimeTask.Result.Start(null);
}

View File

@ -152,7 +152,7 @@ namespace LibationAvalonia.ViewModels
finally
{
if (Result == ProcessBookResult.None)
Result = showRetry(LibraryBook);
Result = await showRetry(LibraryBook);
Status = Result switch
{
@ -313,7 +313,7 @@ namespace LibationAvalonia.ViewModels
#region Failure Handler
private ProcessBookResult showRetry(LibraryBook libraryBook)
private async Task<ProcessBookResult> showRetry(LibraryBook libraryBook)
{
Logger.Error("ERROR. All books have not been processed. Most recent book: processing failed");
@ -346,7 +346,7 @@ $@" Title: {libraryBook.Book.Title}
}
// if null then ask user
dialogResult ??= MessageBox.Show(string.Format(SkipDialogText + "\r\n\r\nSee Settings to avoid this box in the future.", details), "Skip importing this book?", SkipDialogButtons, MessageBoxIcon.Question, SkipDialogDefaultButton);
dialogResult ??= await MessageBox.Show(string.Format(SkipDialogText + "\r\n\r\nSee Settings to avoid this box in the future.", details), "Skip importing this book?", SkipDialogButtons, MessageBoxIcon.Question, SkipDialogDefaultButton);
if (dialogResult == DialogResult.Abort)
return ProcessBookResult.FailedAbort;

View File

@ -244,7 +244,7 @@ namespace LibationAvalonia.ViewModels
return;
var libraryBooks = selectedBooks.Select(rge => rge.LibraryBook).ToList();
var result = MessageBox.ShowConfirmationDialog(
var result = await MessageBox.ShowConfirmationDialog(
null,
libraryBooks,
$"Are you sure you want to remove {selectedBooks.Count} books from Libation's library?",
@ -317,7 +317,7 @@ namespace LibationAvalonia.ViewModels
}
catch (Exception ex)
{
MessageBox.ShowAdminAlert(
await MessageBox.ShowAdminAlert(
null,
"Error scanning library. You may still manually select books to remove from Libation's library.",
"Error scanning library",

View File

@ -41,11 +41,11 @@ namespace LibationAvalonia.Views
break;
}
MessageBox.Show("Library exported to:\r\n" + fileName, "Library Exported");
await MessageBox.Show("Library exported to:\r\n" + fileName, "Library Exported");
}
catch (Exception ex)
{
MessageBox.ShowAdminAlert(this, "Error attempting to export your library.", "Error exporting", ex);
await MessageBox.ShowAdminAlert(this, "Error attempting to export your library.", "Error exporting", ex);
}
}
}

View File

@ -39,7 +39,7 @@ namespace LibationAvalonia.Views
}
catch (Exception ex)
{
MessageBox.Show($"Bad filter string:\r\n\r\n{ex.Message}", "Bad filter string", MessageBoxButtons.OK, MessageBoxIcon.Error);
await MessageBox.Show($"Bad filter string:\r\n\r\n{ex.Message}", "Bad filter string", MessageBoxButtons.OK, MessageBoxIcon.Error);
// re-apply last good filter
await performFilter(lastGoodFilter);

View File

@ -40,7 +40,7 @@ namespace LibationAvalonia.Views
public async void convertAllM4bToMp3ToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
{
var result = MessageBox.Show(
var result = await MessageBox.Show(
"This converts all m4b titles in your library to mp3 files. Original files are not deleted."
+ "\r\nFor large libraries this will take a long time and will take up more disk space."
+ "\r\n\r\nContinue?"

View File

@ -15,7 +15,7 @@ namespace LibationAvalonia.Views
SetQueueCollapseState(collapseState);
}
public void ProductsDisplay_LiberateClicked(object sender, LibraryBook libraryBook)
public async void ProductsDisplay_LiberateClicked(object sender, LibraryBook libraryBook)
{
try
{
@ -39,7 +39,7 @@ namespace LibationAvalonia.Views
if (!App.GoToFile(filePath?.ShortPathName))
{
var suffix = string.IsNullOrWhiteSpace(filePath) ? "" : $":\r\n{filePath}";
MessageBox.Show($"File not found" + suffix);
await MessageBox.Show($"File not found" + suffix);
}
}
}

View File

@ -26,7 +26,7 @@ namespace LibationAvalonia.Views
public async void noAccountsYetAddAccountToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
MessageBox.Show("To load your Audible library, come back here to the Import menu after adding your account");
await MessageBox.Show("To load your Audible library, come back here to the Import menu after adding your account");
await new Dialogs.AccountsDialog().ShowDialog(this);
}
@ -66,11 +66,11 @@ namespace LibationAvalonia.Views
// this is here instead of ScanEnd so that the following is only possible when it's user-initiated, not automatic loop
if (Configuration.Instance.ShowImportedStats && newAdded > 0)
MessageBox.Show($"Total processed: {totalProcessed}\r\nNew: {newAdded}");
await MessageBox.Show($"Total processed: {totalProcessed}\r\nNew: {newAdded}");
}
catch (Exception ex)
{
MessageBox.ShowAdminAlert(
await MessageBox.ShowAdminAlert(
this,
"Error importing library. Please try again. If this still happens after 2 or 3 tries, stop and contact administrator",
"Error importing library",

View File

@ -8,11 +8,13 @@ namespace LibationAvalonia.Views
{
private void Configure_Settings() { }
public async void accountsToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) => await new Dialogs.AccountsDialog().ShowDialog(this);
public async void accountsToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> await new Dialogs.AccountsDialog().ShowDialog(this);
public async void basicSettingsToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) => await new Dialogs.SettingsDialog().ShowDialog(this);
public async void basicSettingsToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> await new Dialogs.SettingsDialog().ShowDialog(this);
public void aboutToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> MessageBox.Show($"Running Libation version {AppScaffolding.LibationScaffolding.BuildVersion}", $"Libation v{AppScaffolding.LibationScaffolding.BuildVersion}");
public async void aboutToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> await MessageBox.Show($"Running Libation version {AppScaffolding.LibationScaffolding.BuildVersion}", $"Libation v{AppScaffolding.LibationScaffolding.BuildVersion}");
}
}

View File

@ -47,7 +47,7 @@ namespace LibationAvalonia.Views
var visibleLibraryBooks = _viewModel.ProductsDisplay.GetVisibleBookEntries();
var confirmationResult = MessageBox.ShowConfirmationDialog(
var confirmationResult = await MessageBox.ShowConfirmationDialog(
this,
visibleLibraryBooks,
"Are you sure you want to replace tags in {0}?",
@ -70,7 +70,7 @@ namespace LibationAvalonia.Views
var visibleLibraryBooks = _viewModel.ProductsDisplay.GetVisibleBookEntries();
var confirmationResult = MessageBox.ShowConfirmationDialog(
var confirmationResult = await MessageBox.ShowConfirmationDialog(
this,
visibleLibraryBooks,
"Are you sure you want to replace downloaded status in {0}?",
@ -88,7 +88,7 @@ namespace LibationAvalonia.Views
{
var visibleLibraryBooks = _viewModel.ProductsDisplay.GetVisibleBookEntries();
var confirmationResult = MessageBox.ShowConfirmationDialog(
var confirmationResult = await MessageBox.ShowConfirmationDialog(
this,
visibleLibraryBooks,
"Are you sure you want to remove {0} from Libation's library?",

View File

@ -80,7 +80,7 @@ namespace LibationAvalonia.Views
if (string.IsNullOrEmpty(zipFile) || !System.IO.File.Exists(zipFile))
return;
var result = MessageBox.Show($"{upgradeProperties.HtmlUrl}\r\n\r\nWould you like to upgrade now?", "New version available", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
var result = await MessageBox.Show($"{upgradeProperties.HtmlUrl}\r\n\r\nWould you like to upgrade now?", "New version available", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
if (result != DialogResult.Yes)
return;

View File

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using AudibleApi;
using AudibleUtilities;
using LibationWinForms.Dialogs.Login;
@ -14,42 +15,43 @@ namespace LibationWinForms.Login
_account = Dinah.Core.ArgumentValidator.EnsureNotNull(account, nameof(account));
}
public string Get2faCode()
public Task<string> Get2faCodeAsync()
{
using var dialog = new _2faCodeDialog();
if (ShowDialog(dialog))
return dialog.Code;
return null;
return Task.FromResult(dialog.Code);
return Task.FromResult<string>(null);
}
public string GetCaptchaAnswer(byte[] captchaImage)
public Task<string> GetCaptchaAnswerAsync(byte[] captchaImage)
{
using var dialog = new CaptchaDialog(captchaImage);
if (ShowDialog(dialog))
return dialog.Answer;
return null;
return Task.FromResult(dialog.Answer);
return Task.FromResult<string>(null);
}
public (string name, string value) GetMfaChoice(MfaConfig mfaConfig)
public Task<(string name, string value)> GetMfaChoiceAsync(MfaConfig mfaConfig)
{
using var dialog = new MfaDialog(mfaConfig);
if (ShowDialog(dialog))
return (dialog.SelectedName, dialog.SelectedValue);
return (null, null);
return Task.FromResult((dialog.SelectedName, dialog.SelectedValue));
return Task.FromResult<(string, string)>((null, null));
}
public (string email, string password) GetLogin()
public Task<(string email, string password)> GetLoginAsync()
{
using var dialog = new LoginCallbackDialog(_account);
if (ShowDialog(dialog))
return (dialog.Email, dialog.Password);
return (null, null);
return Task.FromResult((dialog.Email, dialog.Password));
return Task.FromResult<(string, string)>((null, null));
}
public void ShowApprovalNeeded()
public Task ShowApprovalNeededAsync()
{
using var dialog = new ApprovalNeededDialog();
ShowDialog(dialog);
return Task.CompletedTask;
}
}
}

View File

@ -21,7 +21,7 @@ namespace LibationWinForms.Login
LoginCallback = new WinformLoginCallback(_account);
}
public ChoiceOut Start(ChoiceIn choiceIn)
public Task<ChoiceOut> StartAsync(ChoiceIn choiceIn)
{
using var dialog = new LoginChoiceEagerDialog(_account);
@ -31,13 +31,14 @@ namespace LibationWinForms.Login
switch (dialog.LoginMethod)
{
case LoginMethod.Api:
return ChoiceOut.WithApi(dialog.Email, dialog.Password);
return Task.FromResult(ChoiceOut.WithApi(dialog.Email, dialog.Password));
case LoginMethod.External:
{
using var externalDialog = new LoginExternalDialog(_account, choiceIn.LoginUrl);
return ShowDialog(externalDialog)
? ChoiceOut.External(externalDialog.ResponseUrl)
: null;
return Task.FromResult(
ShowDialog(externalDialog)
? ChoiceOut.External(externalDialog.ResponseUrl)
: null);
}
default:
throw new Exception($"Unknown {nameof(LoginMethod)} value");