iCloud special imap handling.
This commit is contained in:
@@ -27,7 +27,7 @@ namespace Wino.Core.Domain.Interfaces
|
|||||||
string dontAskAgainConfigurationKey = "");
|
string dontAskAgainConfigurationKey = "");
|
||||||
Task<bool> ShowCustomThemeBuilderDialogAsync();
|
Task<bool> ShowCustomThemeBuilderDialogAsync();
|
||||||
Task<AccountCreationDialogResult> ShowAccountProviderSelectionDialogAsync(List<IProviderDetail> availableProviders);
|
Task<AccountCreationDialogResult> ShowAccountProviderSelectionDialogAsync(List<IProviderDetail> availableProviders);
|
||||||
IAccountCreationDialog GetAccountCreationDialog(MailProviderType type);
|
IAccountCreationDialog GetAccountCreationDialog(AccountCreationDialogResult accountCreationDialogResult);
|
||||||
Task<List<SharedFile>> PickFilesAsync(params object[] typeFilters);
|
Task<List<SharedFile>> PickFilesAsync(params object[] typeFilters);
|
||||||
Task<string> PickFilePathAsync(string saveFileName);
|
Task<string> PickFilePathAsync(string saveFileName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Wino.Core.Domain.Entities.Shared;
|
|||||||
|
|
||||||
namespace Wino.Core.Domain.Interfaces
|
namespace Wino.Core.Domain.Interfaces
|
||||||
{
|
{
|
||||||
public interface ICustomServerAccountCreationDialog : IAccountCreationDialog
|
public interface IImapAccountCreationDialog : IAccountCreationDialog
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the custom server information from the dialog..
|
/// Returns the custom server information from the dialog..
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using Wino.Core.Domain.Entities.Shared;
|
||||||
|
using Wino.Core.Domain.Models.Accounts;
|
||||||
|
|
||||||
|
namespace Wino.Core.Domain.Interfaces
|
||||||
|
{
|
||||||
|
public interface ISpecialImapProviderConfigResolver
|
||||||
|
{
|
||||||
|
CustomServerInformation GetServerInformation(MailAccount account, AccountCreationDialogResult dialogResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
namespace Wino.Core.Domain.Models.Accounts
|
namespace Wino.Core.Domain.Models.Accounts
|
||||||
{
|
{
|
||||||
public record AccountCreationDialogResult(MailProviderType ProviderType, string AccountName, string AccountColorHex = "");
|
public record AccountCreationDialogResult(MailProviderType ProviderType, string AccountName, SpecialImapProviderDetails SpecialImapProviderDetails);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
using Wino.Core.Domain.Enums;
|
||||||
|
|
||||||
|
namespace Wino.Core.Domain.Models.Accounts
|
||||||
|
{
|
||||||
|
public record SpecialImapProviderDetails(string Address, string Password, string SenderName, SpecialImapProvider SpecialImapProvider);
|
||||||
|
}
|
||||||
132
Wino.Core.UWP/Controls/AccountCreationDialogControl.xaml
Normal file
132
Wino.Core.UWP/Controls/AccountCreationDialogControl.xaml
Normal file
File diff suppressed because one or more lines are too long
76
Wino.Core.UWP/Controls/AccountCreationDialogControl.xaml.cs
Normal file
76
Wino.Core.UWP/Controls/AccountCreationDialogControl.xaml.cs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Wino.Core.Domain.Enums;
|
||||||
|
using Wino.Core.Domain.Interfaces;
|
||||||
|
using Wino.Messaging.UI;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Wino.Core.UWP.Controls
|
||||||
|
{
|
||||||
|
public sealed partial class AccountCreationDialogControl : UserControl, IRecipient<CopyAuthURLRequested>
|
||||||
|
{
|
||||||
|
private string copyClipboardURL;
|
||||||
|
|
||||||
|
public event EventHandler CancelClicked;
|
||||||
|
|
||||||
|
public AccountCreationDialogState State
|
||||||
|
{
|
||||||
|
get { return (AccountCreationDialogState)GetValue(StateProperty); }
|
||||||
|
set { SetValue(StateProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty StateProperty = DependencyProperty.Register(nameof(State), typeof(AccountCreationDialogState), typeof(AccountCreationDialogControl), new PropertyMetadata(AccountCreationDialogState.Idle, new PropertyChangedCallback(OnStateChanged)));
|
||||||
|
|
||||||
|
public AccountCreationDialogControl()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnStateChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||||
|
{
|
||||||
|
if (obj is AccountCreationDialogControl dialog)
|
||||||
|
{
|
||||||
|
dialog.UpdateVisualStates();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateVisualStates() => VisualStateManager.GoToState(this, State.ToString(), false);
|
||||||
|
|
||||||
|
public async void Receive(CopyAuthURLRequested message)
|
||||||
|
{
|
||||||
|
copyClipboardURL = message.AuthURL;
|
||||||
|
|
||||||
|
await Task.Delay(2000);
|
||||||
|
|
||||||
|
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
|
||||||
|
{
|
||||||
|
AuthHelpDialogButton.Visibility = Windows.UI.Xaml.Visibility.Visible;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ControlLoaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
WeakReferenceMessenger.Default.Register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ControlUnloaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
WeakReferenceMessenger.Default.UnregisterAll(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void CopyClicked(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(copyClipboardURL)) return;
|
||||||
|
|
||||||
|
var clipboardService = WinoApplication.Current.Services.GetService<IClipboardService>();
|
||||||
|
await clipboardService.CopyClipboardAsync(copyClipboardURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void CancelButtonClicked(object sender, Windows.UI.Xaml.RoutedEventArgs e) => CancelClicked?.Invoke(this, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,50 +1,58 @@
|
|||||||
using System;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Interfaces;
|
||||||
using Wino.Core.UWP;
|
|
||||||
using Wino.Messaging.UI;
|
|
||||||
|
|
||||||
namespace Wino.Dialogs
|
namespace Wino.Dialogs
|
||||||
{
|
{
|
||||||
public sealed partial class AccountCreationDialog : BaseAccountCreationDialog, IRecipient<CopyAuthURLRequested>
|
public sealed partial class AccountCreationDialog : ContentDialog, IAccountCreationDialog
|
||||||
{
|
{
|
||||||
private string copyClipboardURL;
|
public CancellationTokenSource CancellationTokenSource { get; private set; }
|
||||||
|
|
||||||
|
public AccountCreationDialogState State
|
||||||
|
{
|
||||||
|
get { return (AccountCreationDialogState)GetValue(StateProperty); }
|
||||||
|
set { SetValue(StateProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty StateProperty = DependencyProperty.Register(nameof(State), typeof(AccountCreationDialogState), typeof(AccountCreationDialog), new PropertyMetadata(AccountCreationDialogState.Idle));
|
||||||
|
|
||||||
public AccountCreationDialog()
|
public AccountCreationDialog()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
WeakReferenceMessenger.Default.Register(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnStateChanged(AccountCreationDialogState state)
|
// Prevent users from dismissing it by ESC key.
|
||||||
|
public void DialogClosing(ContentDialog sender, ContentDialogClosingEventArgs args)
|
||||||
{
|
{
|
||||||
var tt = VisualStateManager.GoToState(this, state.ToString(), true);
|
if (args.Result == ContentDialogResult.None)
|
||||||
}
|
|
||||||
|
|
||||||
public async void Receive(CopyAuthURLRequested message)
|
|
||||||
{
|
|
||||||
copyClipboardURL = message.AuthURL;
|
|
||||||
|
|
||||||
await Task.Delay(2000);
|
|
||||||
|
|
||||||
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
|
|
||||||
{
|
{
|
||||||
AuthHelpDialogButton.Visibility = Windows.UI.Xaml.Visibility.Visible;
|
args.Cancel = true;
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CancelClicked(object sender, Windows.UI.Xaml.RoutedEventArgs e) => Complete(true);
|
public void ShowDialog(CancellationTokenSource cancellationTokenSource)
|
||||||
|
|
||||||
private async void CopyClicked(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(copyClipboardURL)) return;
|
CancellationTokenSource = cancellationTokenSource;
|
||||||
|
|
||||||
var clipboardService = WinoApplication.Current.Services.GetService<IClipboardService>();
|
_ = ShowAsync();
|
||||||
await clipboardService.CopyClipboardAsync(copyClipboardURL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Complete(bool cancel)
|
||||||
|
{
|
||||||
|
State = cancel ? AccountCreationDialogState.Canceled : AccountCreationDialogState.Completed;
|
||||||
|
|
||||||
|
// Unregister from closing event.
|
||||||
|
Closing -= DialogClosing;
|
||||||
|
|
||||||
|
if (cancel && !CancellationTokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
CancellationTokenSource.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
Hide();
|
||||||
|
}
|
||||||
|
private void CancelClicked(object sender, System.EventArgs e) => Complete(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
using System.Threading;
|
|
||||||
using Windows.UI.Xaml;
|
|
||||||
using Windows.UI.Xaml.Controls;
|
|
||||||
using Wino.Core.Domain.Enums;
|
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
|
|
||||||
namespace Wino.Dialogs
|
|
||||||
{
|
|
||||||
public abstract class BaseAccountCreationDialog : ContentDialog, IAccountCreationDialog
|
|
||||||
{
|
|
||||||
public AccountCreationDialogState State
|
|
||||||
{
|
|
||||||
get { return (AccountCreationDialogState)GetValue(StateProperty); }
|
|
||||||
set { SetValue(StateProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public CancellationTokenSource CancellationTokenSource { get; private set; }
|
|
||||||
|
|
||||||
public static readonly DependencyProperty StateProperty = DependencyProperty.Register(nameof(State), typeof(AccountCreationDialogState), typeof(BaseAccountCreationDialog), new PropertyMetadata(AccountCreationDialogState.Idle, OnStateChanged));
|
|
||||||
|
|
||||||
private static void OnStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
var dialog = d as BaseAccountCreationDialog;
|
|
||||||
dialog.OnStateChanged((AccountCreationDialogState)e.NewValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void OnStateChanged(AccountCreationDialogState state);
|
|
||||||
|
|
||||||
// Prevent users from dismissing it by ESC key.
|
|
||||||
public void DialogClosing(ContentDialog sender, ContentDialogClosingEventArgs args)
|
|
||||||
{
|
|
||||||
if (args.Result == ContentDialogResult.None)
|
|
||||||
{
|
|
||||||
args.Cancel = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShowDialog(CancellationTokenSource cancellationTokenSource)
|
|
||||||
{
|
|
||||||
CancellationTokenSource = cancellationTokenSource;
|
|
||||||
|
|
||||||
_ = ShowAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Complete(bool cancel)
|
|
||||||
{
|
|
||||||
State = cancel ? AccountCreationDialogState.Canceled : AccountCreationDialogState.Completed;
|
|
||||||
|
|
||||||
// Unregister from closing event.
|
|
||||||
Closing -= DialogClosing;
|
|
||||||
|
|
||||||
if (cancel && !CancellationTokenSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
CancellationTokenSource.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
Hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -85,6 +85,7 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
@@ -103,20 +104,27 @@
|
|||||||
Source="{x:Bind SelectedMailProvider.ProviderImage, Mode=OneWay}" />
|
Source="{x:Bind SelectedMailProvider.ProviderImage, Mode=OneWay}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
x:Name="SpecialImapAddress"
|
x:Name="DisplayNameTextBox"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
TextChanged="InputChanged"
|
Header="Display Name"
|
||||||
|
PlaceholderText="eg. John Doe"
|
||||||
|
TextChanged="InputChanged" />
|
||||||
|
|
||||||
|
<TextBox
|
||||||
|
x:Name="SpecialImapAddress"
|
||||||
|
Grid.Row="2"
|
||||||
Header="E-mail Address"
|
Header="E-mail Address"
|
||||||
PlaceholderText="eg. johndoe@testmail.com" />
|
PlaceholderText="eg. johndoe@testmail.com"
|
||||||
|
TextChanged="InputChanged" />
|
||||||
|
|
||||||
<PasswordBox
|
<PasswordBox
|
||||||
x:Name="AppSpecificPassword"
|
x:Name="AppSpecificPassword"
|
||||||
PasswordChanged="ImapPasswordChanged"
|
Grid.Row="3"
|
||||||
Grid.Row="2"
|
Header="App-Specific Password"
|
||||||
Header="App-Specific Password" />
|
PasswordChanged="ImapPasswordChanged" />
|
||||||
|
|
||||||
<HyperlinkButton
|
<HyperlinkButton
|
||||||
Grid.Row="3"
|
Grid.Row="4"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Click="AppSpecificHelpButtonClicked"
|
Click="AppSpecificHelpButtonClicked"
|
||||||
Content="How do I get app-specific password?" />
|
Content="How do I get app-specific password?" />
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ namespace Wino.Core.UWP.Dialogs
|
|||||||
public static readonly DependencyProperty IsSpecialImapServerPartVisibleProperty = DependencyProperty.Register(nameof(IsSpecialImapServerPartVisible), typeof(bool), typeof(NewAccountDialog), new PropertyMetadata(false));
|
public static readonly DependencyProperty IsSpecialImapServerPartVisibleProperty = DependencyProperty.Register(nameof(IsSpecialImapServerPartVisible), typeof(bool), typeof(NewAccountDialog), new PropertyMetadata(false));
|
||||||
public static readonly DependencyProperty SelectedMailProviderProperty = DependencyProperty.Register(nameof(SelectedMailProvider), typeof(ProviderDetail), typeof(NewAccountDialog), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedProviderChanged)));
|
public static readonly DependencyProperty SelectedMailProviderProperty = DependencyProperty.Register(nameof(SelectedMailProvider), typeof(ProviderDetail), typeof(NewAccountDialog), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedProviderChanged)));
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets current selected mail provider in the dialog.
|
/// Gets or sets current selected mail provider in the dialog.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -69,6 +70,17 @@ namespace Wino.Core.UWP.Dialogs
|
|||||||
|
|
||||||
private void CreateClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
private void CreateClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||||
{
|
{
|
||||||
|
if (IsSpecialImapServerPartVisible)
|
||||||
|
{
|
||||||
|
// Special imap detail input.
|
||||||
|
|
||||||
|
var details = new SpecialImapProviderDetails(SpecialImapAddress.Text.Trim(), AppSpecificPassword.Password.Trim(), DisplayNameTextBox.Text.Trim(), SelectedMailProvider.SpecialImapProvider);
|
||||||
|
Result = new AccountCreationDialogResult(SelectedMailProvider.Type, AccountNameTextbox.Text.Trim(), details);
|
||||||
|
Hide();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Validate();
|
Validate();
|
||||||
|
|
||||||
if (IsSecondaryButtonEnabled)
|
if (IsSecondaryButtonEnabled)
|
||||||
@@ -85,7 +97,7 @@ namespace Wino.Core.UWP.Dialogs
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Result = new AccountCreationDialogResult(SelectedMailProvider.Type, AccountNameTextbox.Text.Trim());
|
Result = new AccountCreationDialogResult(SelectedMailProvider.Type, AccountNameTextbox.Text.Trim(), null);
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,7 +118,9 @@ namespace Wino.Core.UWP.Dialogs
|
|||||||
bool shouldEnable = SelectedMailProvider != null
|
bool shouldEnable = SelectedMailProvider != null
|
||||||
&& SelectedMailProvider.IsSupported
|
&& SelectedMailProvider.IsSupported
|
||||||
&& !string.IsNullOrEmpty(AccountNameTextbox.Text)
|
&& !string.IsNullOrEmpty(AccountNameTextbox.Text)
|
||||||
&& (IsSpecialImapServerPartVisible ? (!string.IsNullOrEmpty(AppSpecificPassword.Password) && EmailValidation.EmailValidator.Validate(SpecialImapAddress.Text)) : true);
|
&& (IsSpecialImapServerPartVisible ? (!string.IsNullOrEmpty(AppSpecificPassword.Password)
|
||||||
|
&& !string.IsNullOrEmpty(DisplayNameTextBox.Text)
|
||||||
|
&& EmailValidation.EmailValidator.Validate(SpecialImapAddress.Text)) : true);
|
||||||
|
|
||||||
IsPrimaryButtonEnabled = shouldEnable;
|
IsPrimaryButtonEnabled = shouldEnable;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ namespace Wino.Core.UWP.Services
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IAccountCreationDialog GetAccountCreationDialog(MailProviderType type)
|
public virtual IAccountCreationDialog GetAccountCreationDialog(AccountCreationDialogResult accountCreationDialogResult)
|
||||||
{
|
{
|
||||||
return new AccountCreationDialog
|
return new AccountCreationDialog
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -84,6 +84,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Activation\ActivationHandler.cs" />
|
<Compile Include="Activation\ActivationHandler.cs" />
|
||||||
<Compile Include="BasePage.cs" />
|
<Compile Include="BasePage.cs" />
|
||||||
|
<Compile Include="Controls\AccountCreationDialogControl.xaml.cs">
|
||||||
|
<DependentUpon>AccountCreationDialogControl.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Controls\ControlConstants.cs" />
|
<Compile Include="Controls\ControlConstants.cs" />
|
||||||
<Compile Include="Controls\CustomWrapPanel.cs" />
|
<Compile Include="Controls\CustomWrapPanel.cs" />
|
||||||
<Compile Include="Controls\EqualGridPanel.cs" />
|
<Compile Include="Controls\EqualGridPanel.cs" />
|
||||||
@@ -115,7 +118,6 @@
|
|||||||
<Compile Include="Dialogs\AccountPickerDialog.xaml.cs">
|
<Compile Include="Dialogs\AccountPickerDialog.xaml.cs">
|
||||||
<DependentUpon>AccountPickerDialog.xaml</DependentUpon>
|
<DependentUpon>AccountPickerDialog.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Dialogs\BaseAccountCreationDialog.cs" />
|
|
||||||
<Compile Include="Dialogs\CustomMessageDialogInformationContainer.cs" />
|
<Compile Include="Dialogs\CustomMessageDialogInformationContainer.cs" />
|
||||||
<Compile Include="Dialogs\CustomThemeBuilderDialog.xaml.cs">
|
<Compile Include="Dialogs\CustomThemeBuilderDialog.xaml.cs">
|
||||||
<DependentUpon>CustomThemeBuilderDialog.xaml</DependentUpon>
|
<DependentUpon>CustomThemeBuilderDialog.xaml</DependentUpon>
|
||||||
@@ -341,6 +343,10 @@
|
|||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Page Include="Controls\AccountCreationDialogControl.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="Controls\WinoAppTitleBar.xaml">
|
<Page Include="Controls\WinoAppTitleBar.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
|
|||||||
@@ -626,13 +626,21 @@ namespace Wino.Core.Synchronizers.Mail
|
|||||||
|
|
||||||
IImapClient availableClient = null;
|
IImapClient availableClient = null;
|
||||||
|
|
||||||
|
retry:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
availableClient = await _clientPool.GetClientAsync().ConfigureAwait(false);
|
availableClient = await _clientPool.GetClientAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
var strategy = _imapSynchronizationStrategyProvider.GetSynchronizationStrategy(availableClient);
|
var strategy = _imapSynchronizationStrategyProvider.GetSynchronizationStrategy(availableClient);
|
||||||
return await strategy.HandleSynchronizationAsync(availableClient, folder, this, cancellationToken).ConfigureAwait(false);
|
return await strategy.HandleSynchronizationAsync(availableClient, folder, this, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
_clientPool.Release(availableClient, false);
|
||||||
|
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -28,18 +28,25 @@ namespace Wino.Mail.ViewModels
|
|||||||
{
|
{
|
||||||
public partial class AccountManagementViewModel : AccountManagementPageViewModelBase
|
public partial class AccountManagementViewModel : AccountManagementPageViewModelBase
|
||||||
{
|
{
|
||||||
|
private readonly ISpecialImapProviderConfigResolver _specialImapProviderConfigResolver;
|
||||||
|
private readonly IImapTestService _imapTestService;
|
||||||
|
|
||||||
public IMailDialogService MailDialogService { get; }
|
public IMailDialogService MailDialogService { get; }
|
||||||
|
|
||||||
public AccountManagementViewModel(IMailDialogService dialogService,
|
public AccountManagementViewModel(IMailDialogService dialogService,
|
||||||
IWinoServerConnectionManager winoServerConnectionManager,
|
IWinoServerConnectionManager winoServerConnectionManager,
|
||||||
INavigationService navigationService,
|
INavigationService navigationService,
|
||||||
IAccountService accountService,
|
IAccountService accountService,
|
||||||
|
ISpecialImapProviderConfigResolver specialImapProviderConfigResolver,
|
||||||
IProviderService providerService,
|
IProviderService providerService,
|
||||||
|
IImapTestService imapTestService,
|
||||||
IStoreManagementService storeManagementService,
|
IStoreManagementService storeManagementService,
|
||||||
IAuthenticationProvider authenticationProvider,
|
IAuthenticationProvider authenticationProvider,
|
||||||
IPreferencesService preferencesService) : base(dialogService, winoServerConnectionManager, navigationService, accountService, providerService, storeManagementService, authenticationProvider, preferencesService)
|
IPreferencesService preferencesService) : base(dialogService, winoServerConnectionManager, navigationService, accountService, providerService, storeManagementService, authenticationProvider, preferencesService)
|
||||||
{
|
{
|
||||||
MailDialogService = dialogService;
|
MailDialogService = dialogService;
|
||||||
|
_specialImapProviderConfigResolver = specialImapProviderConfigResolver;
|
||||||
|
_imapTestService = imapTestService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
@@ -93,7 +100,7 @@ namespace Wino.Mail.ViewModels
|
|||||||
|
|
||||||
if (accountCreationDialogResult != null)
|
if (accountCreationDialogResult != null)
|
||||||
{
|
{
|
||||||
creationDialog = MailDialogService.GetAccountCreationDialog(accountCreationDialogResult.ProviderType);
|
creationDialog = MailDialogService.GetAccountCreationDialog(accountCreationDialogResult);
|
||||||
|
|
||||||
CustomServerInformation customServerInformation = null;
|
CustomServerInformation customServerInformation = null;
|
||||||
|
|
||||||
@@ -101,17 +108,20 @@ namespace Wino.Mail.ViewModels
|
|||||||
{
|
{
|
||||||
ProviderType = accountCreationDialogResult.ProviderType,
|
ProviderType = accountCreationDialogResult.ProviderType,
|
||||||
Name = accountCreationDialogResult.AccountName,
|
Name = accountCreationDialogResult.AccountName,
|
||||||
AccountColorHex = accountCreationDialogResult.AccountColorHex,
|
SpecialImapProvider = accountCreationDialogResult.SpecialImapProviderDetails?.SpecialImapProvider ?? SpecialImapProvider.None,
|
||||||
Id = Guid.NewGuid()
|
Id = Guid.NewGuid()
|
||||||
};
|
};
|
||||||
|
|
||||||
creationDialog.ShowDialog(accountCreationCancellationTokenSource);
|
creationDialog.ShowDialog(accountCreationCancellationTokenSource);
|
||||||
|
|
||||||
|
await Task.Delay(1000);
|
||||||
|
|
||||||
creationDialog.State = AccountCreationDialogState.SigningIn;
|
creationDialog.State = AccountCreationDialogState.SigningIn;
|
||||||
|
|
||||||
string tokenInformation = string.Empty;
|
string tokenInformation = string.Empty;
|
||||||
|
|
||||||
// Custom server implementation requires more async waiting.
|
// Custom server implementation requires more async waiting.
|
||||||
if (creationDialog is ICustomServerAccountCreationDialog customServerDialog)
|
if (creationDialog is IImapAccountCreationDialog customServerDialog)
|
||||||
{
|
{
|
||||||
// Pass along the account properties and perform initial navigation on the imap frame.
|
// Pass along the account properties and perform initial navigation on the imap frame.
|
||||||
customServerDialog.StartImapConnectionSetup(createdAccount);
|
customServerDialog.StartImapConnectionSetup(createdAccount);
|
||||||
@@ -130,20 +140,35 @@ namespace Wino.Mail.ViewModels
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// OAuth authentication is handled here.
|
if (accountCreationDialogResult.SpecialImapProviderDetails != null)
|
||||||
// Server authenticates, returns the token info here.
|
{
|
||||||
|
createdAccount.SenderName = accountCreationDialogResult.SpecialImapProviderDetails.SenderName;
|
||||||
|
createdAccount.Address = customServerInformation.Address;
|
||||||
|
|
||||||
var tokenInformationResponse = await WinoServerConnectionManager
|
// Special imap provider testing dialog. This is only available for iCloud and Yahoo.
|
||||||
.GetResponseAsync<TokenInformationEx, AuthorizationRequested>(new AuthorizationRequested(accountCreationDialogResult.ProviderType,
|
customServerInformation = _specialImapProviderConfigResolver.GetServerInformation(createdAccount, accountCreationDialogResult);
|
||||||
createdAccount,
|
customServerInformation.Id = Guid.NewGuid();
|
||||||
createdAccount.ProviderType == MailProviderType.Gmail), accountCreationCancellationTokenSource.Token);
|
customServerInformation.AccountId = createdAccount.Id;
|
||||||
|
|
||||||
if (creationDialog.State == AccountCreationDialogState.Canceled)
|
await _imapTestService.TestImapConnectionAsync(customServerInformation, true);
|
||||||
throw new AccountSetupCanceledException();
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// OAuth authentication is handled here.
|
||||||
|
// Server authenticates, returns the token info here.
|
||||||
|
|
||||||
createdAccount.Address = tokenInformationResponse.Data.AccountAddress;
|
var tokenInformationResponse = await WinoServerConnectionManager
|
||||||
|
.GetResponseAsync<TokenInformationEx, AuthorizationRequested>(new AuthorizationRequested(accountCreationDialogResult.ProviderType,
|
||||||
|
createdAccount,
|
||||||
|
createdAccount.ProviderType == MailProviderType.Gmail), accountCreationCancellationTokenSource.Token);
|
||||||
|
|
||||||
tokenInformationResponse.ThrowIfFailed();
|
if (creationDialog.State == AccountCreationDialogState.Canceled)
|
||||||
|
throw new AccountSetupCanceledException();
|
||||||
|
|
||||||
|
createdAccount.Address = tokenInformationResponse.Data.AccountAddress;
|
||||||
|
|
||||||
|
tokenInformationResponse.ThrowIfFailed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address is still doesn't have a value for API synchronizers.
|
// Address is still doesn't have a value for API synchronizers.
|
||||||
@@ -183,7 +208,7 @@ namespace Wino.Mail.ViewModels
|
|||||||
await AccountService.UpdateProfileInformationAsync(createdAccount.Id, profileSynchronizationResult.ProfileInformation);
|
await AccountService.UpdateProfileInformationAsync(createdAccount.Id, profileSynchronizationResult.ProfileInformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creationDialog is ICustomServerAccountCreationDialog customServerAccountCreationDialog)
|
if (creationDialog is IImapAccountCreationDialog customServerAccountCreationDialog)
|
||||||
customServerAccountCreationDialog.ShowPreparingFolders();
|
customServerAccountCreationDialog.ShowPreparingFolders();
|
||||||
else
|
else
|
||||||
creationDialog.State = AccountCreationDialogState.PreparingFolders;
|
creationDialog.State = AccountCreationDialogState.PreparingFolders;
|
||||||
@@ -227,14 +252,6 @@ namespace Wino.Mail.ViewModels
|
|||||||
await AccountService.CreateRootAliasAsync(createdAccount.Id, createdAccount.Address);
|
await AccountService.CreateRootAliasAsync(createdAccount.Id, createdAccount.Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Temporary disabled. Is this even needed? Users can configure special folders manually later on if discovery fails.
|
|
||||||
// Check if Inbox folder is available for the account after synchronization.
|
|
||||||
|
|
||||||
//var isInboxAvailable = await _folderService.IsInboxAvailableForAccountAsync(createdAccount.Id);
|
|
||||||
|
|
||||||
//if (!isInboxAvailable)
|
|
||||||
// throw new Exception(Translator.Exception_InboxNotAvailable);
|
|
||||||
|
|
||||||
// Send changes to listeners.
|
// Send changes to listeners.
|
||||||
ReportUIChange(new AccountCreatedMessage(createdAccount));
|
ReportUIChange(new AccountCreatedMessage(createdAccount));
|
||||||
|
|
||||||
@@ -250,6 +267,10 @@ namespace Wino.Mail.ViewModels
|
|||||||
{
|
{
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
catch (ImapClientPoolException clientPoolException)
|
||||||
|
{
|
||||||
|
DialogService.InfoBarMessage(Translator.Info_AccountCreationFailedTitle, clientPoolException.InnerException.Message, InfoBarMessageType.Error);
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Error(ex, WinoErrors.AccountCreation);
|
Log.Error(ex, WinoErrors.AccountCreation);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Windows.UI.Xaml.Media.Animation;
|
|||||||
using Wino.Core.Domain.Entities.Shared;
|
using Wino.Core.Domain.Entities.Shared;
|
||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Interfaces;
|
||||||
|
using Wino.Core.Domain.Models.Accounts;
|
||||||
using Wino.Messaging.Client.Mails;
|
using Wino.Messaging.Client.Mails;
|
||||||
using Wino.Views.ImapSetup;
|
using Wino.Views.ImapSetup;
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ namespace Wino.Dialogs
|
|||||||
IRecipient<ImapSetupNavigationRequested>,
|
IRecipient<ImapSetupNavigationRequested>,
|
||||||
IRecipient<ImapSetupBackNavigationRequested>,
|
IRecipient<ImapSetupBackNavigationRequested>,
|
||||||
IRecipient<ImapSetupDismissRequested>,
|
IRecipient<ImapSetupDismissRequested>,
|
||||||
ICustomServerAccountCreationDialog
|
IImapAccountCreationDialog
|
||||||
{
|
{
|
||||||
private TaskCompletionSource<CustomServerInformation> _getServerInfoTaskCompletionSource = new TaskCompletionSource<CustomServerInformation>();
|
private TaskCompletionSource<CustomServerInformation> _getServerInfoTaskCompletionSource = new TaskCompletionSource<CustomServerInformation>();
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ namespace Wino.Dialogs
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void StartImapConnectionSetup(MailAccount account) => ImapFrame.Navigate(typeof(WelcomeImapSetupPage), account, new DrillInNavigationTransitionInfo());
|
public void StartImapConnectionSetup(MailAccount account) => ImapFrame.Navigate(typeof(WelcomeImapSetupPage), account, new DrillInNavigationTransitionInfo());
|
||||||
|
public void StartImapConnectionSetup(AccountCreationDialogResult accountCreationDialogResult) => ImapFrame.Navigate(typeof(WelcomeImapSetupPage), accountCreationDialogResult, new DrillInNavigationTransitionInfo());
|
||||||
|
|
||||||
private void ImapSetupDialogClosed(ContentDialog sender, ContentDialogClosedEventArgs args) => WeakReferenceMessenger.Default.UnregisterAll(this);
|
private void ImapSetupDialogClosed(ContentDialog sender, ContentDialogClosedEventArgs args) => WeakReferenceMessenger.Default.UnregisterAll(this);
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Wino.Core.Domain.Entities.Mail;
|
|||||||
using Wino.Core.Domain.Entities.Shared;
|
using Wino.Core.Domain.Entities.Shared;
|
||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Interfaces;
|
||||||
|
using Wino.Core.Domain.Models.Accounts;
|
||||||
using Wino.Core.Domain.Models.Folders;
|
using Wino.Core.Domain.Models.Folders;
|
||||||
using Wino.Core.Domain.Models.Synchronization;
|
using Wino.Core.Domain.Models.Synchronization;
|
||||||
using Wino.Core.UWP.Extensions;
|
using Wino.Core.UWP.Extensions;
|
||||||
@@ -29,18 +30,27 @@ namespace Wino.Services
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IAccountCreationDialog GetAccountCreationDialog(MailProviderType type)
|
public override IAccountCreationDialog GetAccountCreationDialog(AccountCreationDialogResult accountCreationDialogResult)
|
||||||
{
|
{
|
||||||
if (type == MailProviderType.IMAP4)
|
if (accountCreationDialogResult.SpecialImapProviderDetails == null)
|
||||||
{
|
{
|
||||||
return new NewImapSetupDialog
|
if (accountCreationDialogResult.ProviderType == MailProviderType.IMAP4)
|
||||||
{
|
{
|
||||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
return new NewImapSetupDialog
|
||||||
};
|
{
|
||||||
|
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return base.GetAccountCreationDialog(accountCreationDialogResult);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return base.GetAccountCreationDialog(type);
|
// Special IMAP provider like iCloud or Yahoo.
|
||||||
|
|
||||||
|
return base.GetAccountCreationDialog(accountCreationDialogResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Wino.Core.Domain;
|
|||||||
using Wino.Core.Domain.Entities.Shared;
|
using Wino.Core.Domain.Entities.Shared;
|
||||||
using Wino.Core.Domain.Exceptions;
|
using Wino.Core.Domain.Exceptions;
|
||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Interfaces;
|
||||||
|
using Wino.Core.Domain.Models.Accounts;
|
||||||
using Wino.Core.Domain.Models.AutoDiscovery;
|
using Wino.Core.Domain.Models.AutoDiscovery;
|
||||||
using Wino.Messaging.Client.Mails;
|
using Wino.Messaging.Client.Mails;
|
||||||
|
|
||||||
@@ -35,6 +36,10 @@ namespace Wino.Views.ImapSetup
|
|||||||
{
|
{
|
||||||
DisplayNameBox.Text = accountProperties.Name;
|
DisplayNameBox.Text = accountProperties.Name;
|
||||||
}
|
}
|
||||||
|
else if (e.Parameter is AccountCreationDialogResult creationDialogResult)
|
||||||
|
{
|
||||||
|
WeakReferenceMessenger.Default.Send(new ImapSetupNavigationRequested(typeof(TestingImapConnectionPage), creationDialogResult));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SignInClicked(object sender, RoutedEventArgs e)
|
private async void SignInClicked(object sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ namespace Wino.Services
|
|||||||
services.AddTransient<IContactService, ContactService>();
|
services.AddTransient<IContactService, ContactService>();
|
||||||
services.AddTransient<ISignatureService, SignatureService>();
|
services.AddTransient<ISignatureService, SignatureService>();
|
||||||
services.AddTransient<IContextMenuItemService, ContextMenuItemService>();
|
services.AddTransient<IContextMenuItemService, ContextMenuItemService>();
|
||||||
|
services.AddTransient<ISpecialImapProviderConfigResolver, SpecialImapProviderConfigResolver>();
|
||||||
|
|
||||||
services.AddSingleton<IThreadingStrategyProvider, ThreadingStrategyProvider>();
|
services.AddSingleton<IThreadingStrategyProvider, ThreadingStrategyProvider>();
|
||||||
services.AddTransient<IOutlookThreadingStrategy, OutlookThreadingStrategy>();
|
services.AddTransient<IOutlookThreadingStrategy, OutlookThreadingStrategy>();
|
||||||
|
|||||||
46
Wino.Services/SpecialImapProviderConfigResolver.cs
Normal file
46
Wino.Services/SpecialImapProviderConfigResolver.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using Wino.Core.Domain.Entities.Shared;
|
||||||
|
using Wino.Core.Domain.Enums;
|
||||||
|
using Wino.Core.Domain.Interfaces;
|
||||||
|
using Wino.Core.Domain.Models.Accounts;
|
||||||
|
|
||||||
|
namespace Wino.Services
|
||||||
|
{
|
||||||
|
public class SpecialImapProviderConfigResolver : ISpecialImapProviderConfigResolver
|
||||||
|
{
|
||||||
|
private readonly CustomServerInformation iCloudServerConfig = new CustomServerInformation()
|
||||||
|
{
|
||||||
|
IncomingServer = "imap.mail.me.com",
|
||||||
|
IncomingServerPort = "993",
|
||||||
|
IncomingServerType = CustomIncomingServerType.IMAP4,
|
||||||
|
IncomingServerSocketOption = ImapConnectionSecurity.Auto,
|
||||||
|
IncomingAuthenticationMethod = ImapAuthenticationMethod.Auto,
|
||||||
|
OutgoingServer = "smtp.mail.me.com",
|
||||||
|
OutgoingServerPort = "587",
|
||||||
|
OutgoingServerSocketOption = ImapConnectionSecurity.Auto,
|
||||||
|
OutgoingAuthenticationMethod = ImapAuthenticationMethod.Auto,
|
||||||
|
MaxConcurrentClients = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public CustomServerInformation GetServerInformation(MailAccount account, AccountCreationDialogResult dialogResult)
|
||||||
|
{
|
||||||
|
CustomServerInformation resolvedConfig = null;
|
||||||
|
|
||||||
|
if (dialogResult.SpecialImapProviderDetails.SpecialImapProvider == SpecialImapProvider.iCloud)
|
||||||
|
{
|
||||||
|
resolvedConfig = iCloudServerConfig;
|
||||||
|
|
||||||
|
// iCloud takes username before the @icloud part for incoming, but full address as outgoing.
|
||||||
|
resolvedConfig.IncomingServerUsername = dialogResult.SpecialImapProviderDetails.Address.Split('@')[0];
|
||||||
|
resolvedConfig.OutgoingServerUsername = dialogResult.SpecialImapProviderDetails.Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in account details.
|
||||||
|
resolvedConfig.Address = dialogResult.SpecialImapProviderDetails.Address;
|
||||||
|
resolvedConfig.IncomingServerPassword = dialogResult.SpecialImapProviderDetails.Password;
|
||||||
|
resolvedConfig.OutgoingServerPassword = dialogResult.SpecialImapProviderDetails.Password;
|
||||||
|
resolvedConfig.DisplayName = dialogResult.SpecialImapProviderDetails.SenderName;
|
||||||
|
return resolvedConfig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user