diff --git a/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginCallback.cs b/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginCallback.cs index bf4f8b56..3e5a5725 100644 --- a/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginCallback.cs +++ b/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginCallback.cs @@ -1,5 +1,6 @@ using AudibleApi; using AudibleUtilities; +using Avalonia.Threading; using LibationUiBase.Forms; using System.Threading.Tasks; @@ -17,42 +18,46 @@ namespace LibationAvalonia.Dialogs.Login } public async Task Get2faCodeAsync(string prompt) - { - var dialog = new _2faCodeDialog(prompt); - if (await dialog.ShowDialogAsync() is DialogResult.OK) - return dialog.Code; - - return null; - } + => await Dispatcher.UIThread.InvokeAsync(async () => + { + var dialog = new _2faCodeDialog(prompt); + if (await dialog.ShowDialogAsync() is DialogResult.OK) + return dialog.Code; + return null; + }); public async Task<(string password, string guess)> GetCaptchaAnswerAsync(string password, byte[] captchaImage) - { - var dialog = new CaptchaDialog(password, captchaImage); - if (await dialog.ShowDialogAsync() is DialogResult.OK) - return (dialog.Password, dialog.Answer); - return (null, null); - } + => await Dispatcher.UIThread.InvokeAsync(async () => + { + var dialog = new CaptchaDialog(password, captchaImage); + if (await dialog.ShowDialogAsync() is DialogResult.OK) + return (dialog.Password, dialog.Answer); + return (null, null); + }); public async Task<(string name, string value)> GetMfaChoiceAsync(MfaConfig mfaConfig) - { - var dialog = new MfaDialog(mfaConfig); - if (await dialog.ShowDialogAsync() is DialogResult.OK) - return (dialog.SelectedName, dialog.SelectedValue); - return (null, null); - } + => await Dispatcher.UIThread.InvokeAsync(async () => + { + var dialog = new MfaDialog(mfaConfig); + if (await dialog.ShowDialogAsync() is DialogResult.OK) + return (dialog.SelectedName, dialog.SelectedValue); + return (null, null); + }); public async Task<(string email, string password)> GetLoginAsync() - { - var dialog = new LoginCallbackDialog(_account); - if (await dialog.ShowDialogAsync() is DialogResult.OK) - return (_account.AccountId, dialog.Password); - return (null, null); - } + => await Dispatcher.UIThread.InvokeAsync(async () => + { + var dialog = new LoginCallbackDialog(_account); + if (await dialog.ShowDialogAsync() is DialogResult.OK) + return (_account.AccountId, dialog.Password); + return (null, null); + }); public async Task ShowApprovalNeededAsync() - { - var dialog = new ApprovalNeededDialog(); - await dialog.ShowDialogAsync(); - } + => await Dispatcher.UIThread.InvokeAsync(async () => + { + var dialog = new ApprovalNeededDialog(); + await dialog.ShowDialogAsync(); + }); } } \ No newline at end of file diff --git a/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs b/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs index d2872e3f..d6745ad5 100644 --- a/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs +++ b/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs @@ -1,5 +1,6 @@ using AudibleApi; using AudibleUtilities; +using Avalonia.Threading; using LibationFileManager; using LibationUiBase.Forms; using System; @@ -21,6 +22,9 @@ namespace LibationAvalonia.Dialogs.Login } public async Task StartAsync(ChoiceIn choiceIn) + => await Dispatcher.UIThread.InvokeAsync(() => StartAsyncInternal(choiceIn)); + + private async Task StartAsyncInternal(ChoiceIn choiceIn) { if (Configuration.IsWindows && Environment.OSVersion.Version.Major >= 10) { diff --git a/Source/LibationAvalonia/Views/MainWindow.axaml.cs b/Source/LibationAvalonia/Views/MainWindow.axaml.cs index e98d71db..ee435f08 100644 --- a/Source/LibationAvalonia/Views/MainWindow.axaml.cs +++ b/Source/LibationAvalonia/Views/MainWindow.axaml.cs @@ -22,7 +22,7 @@ namespace LibationAvalonia.Views public MainWindow() { DataContext = new MainVM(this); - ApiExtended.LoginChoiceFactory = account => new Dialogs.Login.AvaloniaLoginChoiceEager(account); + ApiExtended.LoginChoiceFactory = account => Dispatcher.UIThread.Invoke(() => new Dialogs.Login.AvaloniaLoginChoiceEager(account)); AudibleApiStorage.LoadError += AudibleApiStorage_LoadError; InitializeComponent(); diff --git a/Source/LibationWinForms/Dialogs/Login/WinformLoginBase.cs b/Source/LibationWinForms/Dialogs/Login/WinformLoginBase.cs index 790df589..1fa3f0ac 100644 --- a/Source/LibationWinForms/Dialogs/Login/WinformLoginBase.cs +++ b/Source/LibationWinForms/Dialogs/Login/WinformLoginBase.cs @@ -5,18 +5,19 @@ namespace LibationWinForms.Dialogs.Login { public abstract class WinformLoginBase { - private readonly IWin32Window _owner; - protected WinformLoginBase(IWin32Window owner) + protected Control Owner { get; } + protected WinformLoginBase(Control owner) { - _owner = owner; + Owner = owner; } /// True if ShowDialog's DialogResult == OK protected bool ShowDialog(Form dialog) - { - var result = dialog.ShowDialog(_owner); - Serilog.Log.Logger.Debug("{@DebugInfo}", new { DialogResult = result }); - return result == DialogResult.OK; - } + => Owner.Invoke(() => + { + var result = dialog.ShowDialog(Owner); + Serilog.Log.Logger.Debug("{@DebugInfo}", new { DialogResult = result }); + return result == DialogResult.OK; + }); } } diff --git a/Source/LibationWinForms/Dialogs/Login/WinformLoginCallback.cs b/Source/LibationWinForms/Dialogs/Login/WinformLoginCallback.cs index 92c36c03..699beb74 100644 --- a/Source/LibationWinForms/Dialogs/Login/WinformLoginCallback.cs +++ b/Source/LibationWinForms/Dialogs/Login/WinformLoginCallback.cs @@ -13,48 +13,53 @@ namespace LibationWinForms.Login public string DeviceName { get; } = "Libation"; - public WinformLoginCallback(Account account, IWin32Window owner) : base(owner) + public WinformLoginCallback(Account account, Control owner) : base(owner) { _account = Dinah.Core.ArgumentValidator.EnsureNotNull(account, nameof(account)); } public Task Get2faCodeAsync(string prompt) - { - using var dialog = new _2faCodeDialog(prompt); - if (ShowDialog(dialog)) - return Task.FromResult(dialog.Code); - return Task.FromResult(null); - } + => Owner.Invoke(() => + { + using var dialog = new _2faCodeDialog(prompt); + if (ShowDialog(dialog)) + return Task.FromResult(dialog.Code); + return Task.FromResult(null); + }); public Task<(string password, string guess)> GetCaptchaAnswerAsync(string password, byte[] captchaImage) - { - using var dialog = new CaptchaDialog(password, captchaImage); - if (ShowDialog(dialog)) - return Task.FromResult((dialog.Password, dialog.Answer)); - return Task.FromResult<(string, string)>((null,null)); - } + => Owner.Invoke(() => + { + using var dialog = new CaptchaDialog(password, captchaImage); + if (ShowDialog(dialog)) + return Task.FromResult((dialog.Password, dialog.Answer)); + return Task.FromResult<(string, string)>((null, null)); + }); public Task<(string name, string value)> GetMfaChoiceAsync(MfaConfig mfaConfig) - { - using var dialog = new MfaDialog(mfaConfig); - if (ShowDialog(dialog)) - return Task.FromResult((dialog.SelectedName, dialog.SelectedValue)); - return Task.FromResult<(string, string)>((null, null)); - } + => Owner.Invoke(() => + { + using var dialog = new MfaDialog(mfaConfig); + if (ShowDialog(dialog)) + return Task.FromResult((dialog.SelectedName, dialog.SelectedValue)); + return Task.FromResult<(string, string)>((null, null)); + }); public Task<(string email, string password)> GetLoginAsync() - { - using var dialog = new LoginCallbackDialog(_account); - if (ShowDialog(dialog)) - return Task.FromResult((dialog.Email, dialog.Password)); - return Task.FromResult<(string, string)>((null, null)); - } + => Owner.Invoke(() => + { + using var dialog = new LoginCallbackDialog(_account); + if (ShowDialog(dialog)) + return Task.FromResult((dialog.Email, dialog.Password)); + return Task.FromResult<(string, string)>((null, null)); + }); public Task ShowApprovalNeededAsync() - { - using var dialog = new ApprovalNeededDialog(); - ShowDialog(dialog); - return Task.CompletedTask; - } + => Owner.Invoke(() => + { + using var dialog = new ApprovalNeededDialog(); + ShowDialog(dialog); + return Task.CompletedTask; + }); } } \ No newline at end of file diff --git a/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs b/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs index 48724c7e..787eba5a 100644 --- a/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs +++ b/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs @@ -13,13 +13,16 @@ namespace LibationWinForms.Login private Account _account { get; } - public WinformLoginChoiceEager(Account account, IWin32Window owner) : base(owner) + public WinformLoginChoiceEager(Account account, Control owner) : base(owner) { _account = Dinah.Core.ArgumentValidator.EnsureNotNull(account, nameof(account)); LoginCallback = new WinformLoginCallback(_account, owner); } public Task StartAsync(ChoiceIn choiceIn) + => Owner.Invoke(() => StartAsyncInternal(choiceIn)); + + private Task StartAsyncInternal(ChoiceIn choiceIn) { if (Environment.OSVersion.Version.Major >= 10) {