Form thread safety
This commit is contained in:
parent
7848366818
commit
1fdcea929f
@ -1,5 +1,6 @@
|
|||||||
using AudibleApi;
|
using AudibleApi;
|
||||||
using AudibleUtilities;
|
using AudibleUtilities;
|
||||||
|
using Avalonia.Threading;
|
||||||
using LibationUiBase.Forms;
|
using LibationUiBase.Forms;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -17,42 +18,46 @@ namespace LibationAvalonia.Dialogs.Login
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> Get2faCodeAsync(string prompt)
|
public async Task<string> Get2faCodeAsync(string prompt)
|
||||||
{
|
=> await Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
var dialog = new _2faCodeDialog(prompt);
|
{
|
||||||
if (await dialog.ShowDialogAsync() is DialogResult.OK)
|
var dialog = new _2faCodeDialog(prompt);
|
||||||
return dialog.Code;
|
if (await dialog.ShowDialogAsync() is DialogResult.OK)
|
||||||
|
return dialog.Code;
|
||||||
return null;
|
return null;
|
||||||
}
|
});
|
||||||
|
|
||||||
public async Task<(string password, string guess)> GetCaptchaAnswerAsync(string password, byte[] captchaImage)
|
public async Task<(string password, string guess)> GetCaptchaAnswerAsync(string password, byte[] captchaImage)
|
||||||
{
|
=> await Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
var dialog = new CaptchaDialog(password, captchaImage);
|
{
|
||||||
if (await dialog.ShowDialogAsync() is DialogResult.OK)
|
var dialog = new CaptchaDialog(password, captchaImage);
|
||||||
return (dialog.Password, dialog.Answer);
|
if (await dialog.ShowDialogAsync() is DialogResult.OK)
|
||||||
return (null, null);
|
return (dialog.Password, dialog.Answer);
|
||||||
}
|
return (null, null);
|
||||||
|
});
|
||||||
|
|
||||||
public async Task<(string name, string value)> GetMfaChoiceAsync(MfaConfig mfaConfig)
|
public async Task<(string name, string value)> GetMfaChoiceAsync(MfaConfig mfaConfig)
|
||||||
{
|
=> await Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
var dialog = new MfaDialog(mfaConfig);
|
{
|
||||||
if (await dialog.ShowDialogAsync() is DialogResult.OK)
|
var dialog = new MfaDialog(mfaConfig);
|
||||||
return (dialog.SelectedName, dialog.SelectedValue);
|
if (await dialog.ShowDialogAsync() is DialogResult.OK)
|
||||||
return (null, null);
|
return (dialog.SelectedName, dialog.SelectedValue);
|
||||||
}
|
return (null, null);
|
||||||
|
});
|
||||||
|
|
||||||
public async Task<(string email, string password)> GetLoginAsync()
|
public async Task<(string email, string password)> GetLoginAsync()
|
||||||
{
|
=> await Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
var dialog = new LoginCallbackDialog(_account);
|
{
|
||||||
if (await dialog.ShowDialogAsync() is DialogResult.OK)
|
var dialog = new LoginCallbackDialog(_account);
|
||||||
return (_account.AccountId, dialog.Password);
|
if (await dialog.ShowDialogAsync() is DialogResult.OK)
|
||||||
return (null, null);
|
return (_account.AccountId, dialog.Password);
|
||||||
}
|
return (null, null);
|
||||||
|
});
|
||||||
|
|
||||||
public async Task ShowApprovalNeededAsync()
|
public async Task ShowApprovalNeededAsync()
|
||||||
{
|
=> await Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
var dialog = new ApprovalNeededDialog();
|
{
|
||||||
await dialog.ShowDialogAsync();
|
var dialog = new ApprovalNeededDialog();
|
||||||
}
|
await dialog.ShowDialogAsync();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
using AudibleApi;
|
using AudibleApi;
|
||||||
using AudibleUtilities;
|
using AudibleUtilities;
|
||||||
|
using Avalonia.Threading;
|
||||||
using LibationFileManager;
|
using LibationFileManager;
|
||||||
using LibationUiBase.Forms;
|
using LibationUiBase.Forms;
|
||||||
using System;
|
using System;
|
||||||
@ -21,6 +22,9 @@ namespace LibationAvalonia.Dialogs.Login
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ChoiceOut?> StartAsync(ChoiceIn choiceIn)
|
public async Task<ChoiceOut?> StartAsync(ChoiceIn choiceIn)
|
||||||
|
=> await Dispatcher.UIThread.InvokeAsync(() => StartAsyncInternal(choiceIn));
|
||||||
|
|
||||||
|
private async Task<ChoiceOut?> StartAsyncInternal(ChoiceIn choiceIn)
|
||||||
{
|
{
|
||||||
if (Configuration.IsWindows && Environment.OSVersion.Version.Major >= 10)
|
if (Configuration.IsWindows && Environment.OSVersion.Version.Major >= 10)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -22,7 +22,7 @@ namespace LibationAvalonia.Views
|
|||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
DataContext = new MainVM(this);
|
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;
|
AudibleApiStorage.LoadError += AudibleApiStorage_LoadError;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|||||||
@ -5,18 +5,19 @@ namespace LibationWinForms.Dialogs.Login
|
|||||||
{
|
{
|
||||||
public abstract class WinformLoginBase
|
public abstract class WinformLoginBase
|
||||||
{
|
{
|
||||||
private readonly IWin32Window _owner;
|
protected Control Owner { get; }
|
||||||
protected WinformLoginBase(IWin32Window owner)
|
protected WinformLoginBase(Control owner)
|
||||||
{
|
{
|
||||||
_owner = owner;
|
Owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <returns>True if ShowDialog's DialogResult == OK</returns>
|
/// <returns>True if ShowDialog's DialogResult == OK</returns>
|
||||||
protected bool ShowDialog(Form dialog)
|
protected bool ShowDialog(Form dialog)
|
||||||
{
|
=> Owner.Invoke(() =>
|
||||||
var result = dialog.ShowDialog(_owner);
|
{
|
||||||
Serilog.Log.Logger.Debug("{@DebugInfo}", new { DialogResult = result });
|
var result = dialog.ShowDialog(Owner);
|
||||||
return result == DialogResult.OK;
|
Serilog.Log.Logger.Debug("{@DebugInfo}", new { DialogResult = result });
|
||||||
}
|
return result == DialogResult.OK;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,48 +13,53 @@ namespace LibationWinForms.Login
|
|||||||
|
|
||||||
public string DeviceName { get; } = "Libation";
|
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));
|
_account = Dinah.Core.ArgumentValidator.EnsureNotNull(account, nameof(account));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<string> Get2faCodeAsync(string prompt)
|
public Task<string> Get2faCodeAsync(string prompt)
|
||||||
{
|
=> Owner.Invoke(() =>
|
||||||
using var dialog = new _2faCodeDialog(prompt);
|
{
|
||||||
if (ShowDialog(dialog))
|
using var dialog = new _2faCodeDialog(prompt);
|
||||||
return Task.FromResult(dialog.Code);
|
if (ShowDialog(dialog))
|
||||||
return Task.FromResult<string>(null);
|
return Task.FromResult(dialog.Code);
|
||||||
}
|
return Task.FromResult<string>(null);
|
||||||
|
});
|
||||||
|
|
||||||
public Task<(string password, string guess)> GetCaptchaAnswerAsync(string password, byte[] captchaImage)
|
public Task<(string password, string guess)> GetCaptchaAnswerAsync(string password, byte[] captchaImage)
|
||||||
{
|
=> Owner.Invoke(() =>
|
||||||
using var dialog = new CaptchaDialog(password, captchaImage);
|
{
|
||||||
if (ShowDialog(dialog))
|
using var dialog = new CaptchaDialog(password, captchaImage);
|
||||||
return Task.FromResult((dialog.Password, dialog.Answer));
|
if (ShowDialog(dialog))
|
||||||
return Task.FromResult<(string, string)>((null,null));
|
return Task.FromResult((dialog.Password, dialog.Answer));
|
||||||
}
|
return Task.FromResult<(string, string)>((null, null));
|
||||||
|
});
|
||||||
|
|
||||||
public Task<(string name, string value)> GetMfaChoiceAsync(MfaConfig mfaConfig)
|
public Task<(string name, string value)> GetMfaChoiceAsync(MfaConfig mfaConfig)
|
||||||
{
|
=> Owner.Invoke(() =>
|
||||||
using var dialog = new MfaDialog(mfaConfig);
|
{
|
||||||
if (ShowDialog(dialog))
|
using var dialog = new MfaDialog(mfaConfig);
|
||||||
return Task.FromResult((dialog.SelectedName, dialog.SelectedValue));
|
if (ShowDialog(dialog))
|
||||||
return Task.FromResult<(string, string)>((null, null));
|
return Task.FromResult((dialog.SelectedName, dialog.SelectedValue));
|
||||||
}
|
return Task.FromResult<(string, string)>((null, null));
|
||||||
|
});
|
||||||
|
|
||||||
public Task<(string email, string password)> GetLoginAsync()
|
public Task<(string email, string password)> GetLoginAsync()
|
||||||
{
|
=> Owner.Invoke(() =>
|
||||||
using var dialog = new LoginCallbackDialog(_account);
|
{
|
||||||
if (ShowDialog(dialog))
|
using var dialog = new LoginCallbackDialog(_account);
|
||||||
return Task.FromResult((dialog.Email, dialog.Password));
|
if (ShowDialog(dialog))
|
||||||
return Task.FromResult<(string, string)>((null, null));
|
return Task.FromResult((dialog.Email, dialog.Password));
|
||||||
}
|
return Task.FromResult<(string, string)>((null, null));
|
||||||
|
});
|
||||||
|
|
||||||
public Task ShowApprovalNeededAsync()
|
public Task ShowApprovalNeededAsync()
|
||||||
{
|
=> Owner.Invoke(() =>
|
||||||
using var dialog = new ApprovalNeededDialog();
|
{
|
||||||
ShowDialog(dialog);
|
using var dialog = new ApprovalNeededDialog();
|
||||||
return Task.CompletedTask;
|
ShowDialog(dialog);
|
||||||
}
|
return Task.CompletedTask;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13,13 +13,16 @@ namespace LibationWinForms.Login
|
|||||||
|
|
||||||
private Account _account { get; }
|
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));
|
_account = Dinah.Core.ArgumentValidator.EnsureNotNull(account, nameof(account));
|
||||||
LoginCallback = new WinformLoginCallback(_account, owner);
|
LoginCallback = new WinformLoginCallback(_account, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<ChoiceOut> StartAsync(ChoiceIn choiceIn)
|
public Task<ChoiceOut> StartAsync(ChoiceIn choiceIn)
|
||||||
|
=> Owner.Invoke(() => StartAsyncInternal(choiceIn));
|
||||||
|
|
||||||
|
private Task<ChoiceOut> StartAsyncInternal(ChoiceIn choiceIn)
|
||||||
{
|
{
|
||||||
if (Environment.OSVersion.Version.Major >= 10)
|
if (Environment.OSVersion.Version.Major >= 10)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user