From f0cb9481b0396dc6cba4057502307e14912975bc Mon Sep 17 00:00:00 2001 From: Ben Olden-Cooligan Date: Sat, 25 Mar 2023 10:39:52 -0700 Subject: [PATCH] Refactor email provider display logic --- NAPS2.Lib/EtoForms/Ui/EmailProviderForm.cs | 179 ++---------------- .../Email/EmailProviderController.cs | 155 +++++++++++++++ .../ImportExport/Email/EmailProviderWidget.cs | 12 ++ 3 files changed, 178 insertions(+), 168 deletions(-) create mode 100644 NAPS2.Lib/ImportExport/Email/EmailProviderController.cs create mode 100644 NAPS2.Lib/ImportExport/Email/EmailProviderWidget.cs diff --git a/NAPS2.Lib/EtoForms/Ui/EmailProviderForm.cs b/NAPS2.Lib/EtoForms/Ui/EmailProviderForm.cs index 21b02b23a..1317f1624 100644 --- a/NAPS2.Lib/EtoForms/Ui/EmailProviderForm.cs +++ b/NAPS2.Lib/EtoForms/Ui/EmailProviderForm.cs @@ -2,113 +2,16 @@ using Eto.Drawing; using Eto.Forms; using NAPS2.EtoForms.Layout; using NAPS2.ImportExport.Email; -using NAPS2.ImportExport.Email.Mapi; -using NAPS2.ImportExport.Email.Oauth; -using NAPS2.Scan; namespace NAPS2.EtoForms.Ui; public class EmailProviderForm : EtoDialogBase { - private readonly SystemEmailClients _systemEmailClients; - private readonly GmailOauthProvider _gmailOauthProvider; - private readonly OutlookWebOauthProvider _outlookWebOauthProvider; - private readonly ThunderbirdEmailProvider _thunderbirdProvider; + private readonly EmailProviderController _controller; - private readonly List _providerWidgets; - private readonly string[] _systemClientNames; - private readonly string? _defaultSystemClientName; - - public EmailProviderForm(Naps2Config config, SystemEmailClients systemEmailClients, - GmailOauthProvider gmailOauthProvider, OutlookWebOauthProvider outlookWebOauthProvider, - ThunderbirdEmailProvider thunderbirdProvider) : base(config) + public EmailProviderForm(Naps2Config config, EmailProviderController controller) : base(config) { - _systemEmailClients = systemEmailClients; - _gmailOauthProvider = gmailOauthProvider; - _outlookWebOauthProvider = outlookWebOauthProvider; - _thunderbirdProvider = thunderbirdProvider; - - _providerWidgets = new List(); -#if NET6_0_OR_GREATER - if (!OperatingSystem.IsWindowsVersionAtLeast(7)) - { - _systemClientNames = Array.Empty(); - _defaultSystemClientName = null; - } - else - { -#endif - _systemClientNames = _systemEmailClients.GetNames(); - _defaultSystemClientName = _systemEmailClients.GetDefaultName(); - - foreach (var clientName in _systemClientNames.OrderBy(x => x == _defaultSystemClientName ? 0 : 1)) - { - var exePath = _systemEmailClients.GetExePath(clientName); - var icon = exePath == null ? null : EtoPlatform.Current.ExtractAssociatedIcon(exePath); - _providerWidgets.Add(new EmailProviderWidget - { - ProviderType = EmailProviderType.System, - ProviderIcon = icon ?? Icons.mail_yellow.ToEtoImage(), - ProviderName = clientName, - ClickAction = () => ChooseSystem(clientName) - }); - } -#if NET6_0_OR_GREATER - } - - // For Windows we expect Thunderbird to be used through MAPI. For Linux we need to handle it specially. - if (!OperatingSystem.IsWindows()) - { - _providerWidgets.Add(new EmailProviderWidget - { - ProviderType = EmailProviderType.Thunderbird, - ProviderIcon = Icons.thunderbird.ToEtoImage(), - ProviderName = EmailProviderType.Thunderbird.Description(), - ClickAction = ChooseThunderbird, - // When Thunderbird isn't available, we disable it rather than hide it. - // The point is to give a hint to the user that Thunderbird support is present. - Enabled = _thunderbirdProvider.IsAvailable - }); - } -#endif - - if (_gmailOauthProvider.HasClientCreds) - { - _providerWidgets.Add(new EmailProviderWidget - { - ProviderType = EmailProviderType.Gmail, - ProviderIcon = Icons.gmail.ToEtoImage(), - ProviderName = EmailProviderType.Gmail.Description(), - ClickAction = () => ChooseOauth(_gmailOauthProvider) - }); - } - - if (_outlookWebOauthProvider.HasClientCreds) - { - _providerWidgets.Add(new EmailProviderWidget - { - ProviderType = EmailProviderType.OutlookWeb, - ProviderIcon = Icons.outlookweb.ToEtoImage(), - ProviderName = EmailProviderType.OutlookWeb.Description(), - ClickAction = () => ChooseOauth(_outlookWebOauthProvider) - }); - } - - //providerWidgets.Add(new EmailProviderWidget - //{ - // ProviderType = EmailProviderType.CustomSmtp, - // ProviderIcon = Icons.email_setting, - // ProviderName = EmailProviderType.CustomSmtp.Description(), - // ClickAction = ChooseCustomSmtp - //}); - - // Put the configured provider at the top - var defaultWidget = GetDefaultWidget(); - if (defaultWidget != null) - { - _providerWidgets.Remove(defaultWidget); - _providerWidgets.Insert(0, defaultWidget); - } + _controller = controller; } protected override void BuildLayout() @@ -120,7 +23,14 @@ public class EmailProviderForm : EtoDialogBase LayoutController.DefaultSpacing = 0; LayoutController.Content = L.Column( - _providerWidgets.Select(x => C.Button(new ActionCommand(x.ClickAction) + _controller.GetWidgets().Select(x => C.Button(new ActionCommand(() => + { + if (x.Choose()) + { + Result = true; + Close(); + } + }) { Text = x.ProviderName, Image = x.ProviderIcon, @@ -131,71 +41,4 @@ public class EmailProviderForm : EtoDialogBase public bool Result { get; private set; } - private void ChooseSystem(string clientName) - { - var transact = Config.User.BeginTransaction(); - transact.Remove(c => c.EmailSetup); - transact.Set(c => c.EmailSetup.SystemProviderName, clientName); - transact.Set(c => c.EmailSetup.ProviderType, EmailProviderType.System); - transact.Commit(); - Result = true; - Close(); - } - - private void ChooseThunderbird() - { - var transact = Config.User.BeginTransaction(); - transact.Remove(c => c.EmailSetup); - transact.Set(c => c.EmailSetup.ProviderType, EmailProviderType.Thunderbird); - transact.Commit(); - Result = true; - Close(); - } - - private void ChooseOauth(OauthProvider provider) - { - var authForm = FormFactory.Create(); - authForm.OauthProvider = provider; - authForm.ShowModal(); - if (authForm.Result) - { - Result = true; - Close(); - } - } - - private EmailProviderWidget? GetDefaultWidget() - { - var emailSetup = Config.Get(c => c.EmailSetup); - foreach (var widget in _providerWidgets) - { - if (widget.ProviderType == emailSetup.ProviderType) - { - if (widget.ProviderType == EmailProviderType.System) - { - // System providers need additional logic since there may be more than one - if (widget.ProviderName == emailSetup.SystemProviderName - || string.IsNullOrEmpty(emailSetup.SystemProviderName) && - widget.ProviderName == _defaultSystemClientName) - { - return widget; - } - } - else - { - return widget; - } - } - } - return null; - } - - public class EmailProviderWidget - { - public required EmailProviderType ProviderType { get; init; } - public required Bitmap ProviderIcon { get; init; } - public required string ProviderName { get; init; } - public required Action ClickAction { get; init; } - public bool Enabled { get; set; } = true; - } } \ No newline at end of file diff --git a/NAPS2.Lib/ImportExport/Email/EmailProviderController.cs b/NAPS2.Lib/ImportExport/Email/EmailProviderController.cs new file mode 100644 index 000000000..37de044df --- /dev/null +++ b/NAPS2.Lib/ImportExport/Email/EmailProviderController.cs @@ -0,0 +1,155 @@ +using Eto.Drawing; +using NAPS2.EtoForms; +using NAPS2.EtoForms.Ui; +using NAPS2.ImportExport.Email.Mapi; +using NAPS2.ImportExport.Email.Oauth; +using NAPS2.Scan; + +namespace NAPS2.ImportExport.Email; + +public class EmailProviderController +{ + private readonly IFormFactory _formFactory; + private readonly Naps2Config _config; + private readonly SystemEmailClients _systemEmailClients; + private readonly GmailOauthProvider _gmailOauthProvider; + private readonly OutlookWebOauthProvider _outlookWebOauthProvider; + private readonly ThunderbirdEmailProvider _thunderbirdProvider; + + public EmailProviderController(IFormFactory formFactory, Naps2Config config, SystemEmailClients systemEmailClients, + GmailOauthProvider gmailOauthProvider, OutlookWebOauthProvider outlookWebOauthProvider, + ThunderbirdEmailProvider thunderbirdProvider) + { + _formFactory = formFactory; + _config = config; + _systemEmailClients = systemEmailClients; + _gmailOauthProvider = gmailOauthProvider; + _outlookWebOauthProvider = outlookWebOauthProvider; + _thunderbirdProvider = thunderbirdProvider; + } + + public List GetWidgets() + { + var providerWidgets = new List(); + var userSetup = _config.Get(c => c.EmailSetup); + +#if NET6_0_OR_GREATER + if (OperatingSystem.IsWindowsVersionAtLeast(7)) + { +#endif + var systemClientNames = _systemEmailClients.GetNames(); + var defaultSystemClientName = _systemEmailClients.GetDefaultName(); + + foreach (var clientName in systemClientNames.OrderBy(x => + x == userSetup.SystemProviderName ? 0 : x == defaultSystemClientName ? 1 : 2)) + { + providerWidgets.Add(GetWidget(EmailProviderType.System, clientName)); + } +#if NET6_0_OR_GREATER + } +#endif + + void MaybeAddWidget(EmailProviderType type, bool condition) + { + if (condition) + { + providerWidgets.Add(GetWidget(type)); + } + } + +#if NET6_0_OR_GREATER + // For Windows we expect Thunderbird to be used through MAPI. For Linux we need to handle it specially. + MaybeAddWidget(EmailProviderType.Thunderbird, !OperatingSystem.IsWindows()); +#endif + MaybeAddWidget(EmailProviderType.Gmail, _gmailOauthProvider.HasClientCreds); + MaybeAddWidget(EmailProviderType.OutlookWeb, _outlookWebOauthProvider.HasClientCreds); + + // Sort the currently-selected provider to the top + return providerWidgets.OrderBy(widget => widget.ProviderType == userSetup.ProviderType ? 0 : 1).ToList(); + } + + private EmailProviderWidget GetWidget(EmailProviderType type, string? clientName = null) + { + return type switch + { + EmailProviderType.System => new EmailProviderWidget + { + ProviderType = EmailProviderType.System, + ProviderIcon = GetSystemIcon(clientName!) ?? Icons.mail_yellow.ToEtoImage(), + ProviderName = clientName!, + Choose = () => ChooseSystem(clientName!) + }, + EmailProviderType.Thunderbird => new EmailProviderWidget + { + ProviderType = EmailProviderType.Thunderbird, + ProviderIcon = Icons.thunderbird.ToEtoImage(), + ProviderName = EmailProviderType.Thunderbird.Description(), + Choose = ChooseThunderbird, + // When Thunderbird isn't available, we disable it rather than hide it. + // The point is to give a hint to the user that Thunderbird support is present. + Enabled = _thunderbirdProvider.IsAvailable + }, + EmailProviderType.Gmail => new EmailProviderWidget + { + ProviderType = EmailProviderType.Gmail, + ProviderIcon = Icons.gmail.ToEtoImage(), + ProviderName = EmailProviderType.Gmail.Description(), + Choose = () => ChooseOauth(_gmailOauthProvider) + }, + EmailProviderType.OutlookWeb => new EmailProviderWidget + { + ProviderType = EmailProviderType.OutlookWeb, + ProviderIcon = Icons.outlookweb.ToEtoImage(), + ProviderName = EmailProviderType.OutlookWeb.Description(), + Choose = () => ChooseOauth(_outlookWebOauthProvider) + }, + // EmailProviderType.CustomSmtp => new EmailProviderWidget + // { + // ProviderType = EmailProviderType.CustomSmtp, + // ProviderIcon = Icons.email_setting.ToEtoImage(), + // ProviderName = EmailProviderType.CustomSmtp.Description(), + // Choose = ChooseCustomSmtp + // }, + _ => throw new ArgumentException() + }; + } + + private Bitmap? GetSystemIcon(string clientName) + { +#if NET6_0_OR_GREATER + if (!OperatingSystem.IsWindowsVersionAtLeast(7)) + { + throw new InvalidOperationException(); + } +#endif + var exePath = _systemEmailClients.GetExePath(clientName); + return exePath == null ? null : EtoPlatform.Current.ExtractAssociatedIcon(exePath); + } + + private bool ChooseSystem(string clientName) + { + var transact = _config.User.BeginTransaction(); + transact.Remove(c => c.EmailSetup); + transact.Set(c => c.EmailSetup.SystemProviderName, clientName); + transact.Set(c => c.EmailSetup.ProviderType, EmailProviderType.System); + transact.Commit(); + return true; + } + + private bool ChooseThunderbird() + { + var transact = _config.User.BeginTransaction(); + transact.Remove(c => c.EmailSetup); + transact.Set(c => c.EmailSetup.ProviderType, EmailProviderType.Thunderbird); + transact.Commit(); + return true; + } + + private bool ChooseOauth(OauthProvider provider) + { + var authForm = _formFactory.Create(); + authForm.OauthProvider = provider; + authForm.ShowModal(); + return authForm.Result; + } +} \ No newline at end of file diff --git a/NAPS2.Lib/ImportExport/Email/EmailProviderWidget.cs b/NAPS2.Lib/ImportExport/Email/EmailProviderWidget.cs new file mode 100644 index 000000000..319dc12b6 --- /dev/null +++ b/NAPS2.Lib/ImportExport/Email/EmailProviderWidget.cs @@ -0,0 +1,12 @@ +using Eto.Drawing; + +namespace NAPS2.ImportExport.Email; + +public class EmailProviderWidget +{ + public required EmailProviderType ProviderType { get; init; } + public required Bitmap ProviderIcon { get; init; } + public required string ProviderName { get; init; } + public required Func Choose { get; init; } + public bool Enabled { get; set; } = true; +} \ No newline at end of file