Removed migrations. New onboarding screen and wizard like steps.
This commit is contained in:
@@ -86,249 +86,7 @@ public partial class AccountManagementViewModel : AccountManagementPageViewModel
|
||||
return;
|
||||
}
|
||||
|
||||
MailAccount createdAccount = null;
|
||||
IAccountCreationDialog creationDialog = null;
|
||||
bool creationDialogClosed = false;
|
||||
|
||||
try
|
||||
{
|
||||
var providers = ProviderService.GetAvailableProviders();
|
||||
|
||||
// Select provider.
|
||||
var accountCreationDialogResult = await ExecuteUIThreadTaskAsync(() => MailDialogService.ShowAccountProviderSelectionDialogAsync(providers));
|
||||
|
||||
if (accountCreationDialogResult != null)
|
||||
{
|
||||
CustomServerInformation customServerInformation = null;
|
||||
|
||||
createdAccount = new MailAccount()
|
||||
{
|
||||
ProviderType = accountCreationDialogResult.ProviderType,
|
||||
Name = accountCreationDialogResult.AccountName,
|
||||
SpecialImapProvider = accountCreationDialogResult.SpecialImapProviderDetails?.SpecialImapProvider ?? SpecialImapProvider.None,
|
||||
Id = Guid.NewGuid(),
|
||||
AccountColorHex = accountCreationDialogResult.AccountColorHex,
|
||||
IsCalendarAccessGranted = true // New accounts have calendar scopes
|
||||
};
|
||||
|
||||
if (accountCreationDialogResult.ProviderType == MailProviderType.IMAP4)
|
||||
{
|
||||
if (createdAccount.SpecialImapProvider == SpecialImapProvider.iCloud || createdAccount.SpecialImapProvider == SpecialImapProvider.Yahoo)
|
||||
{
|
||||
var accountCreationCancellationTokenSource = new CancellationTokenSource();
|
||||
creationDialog = MailDialogService.GetAccountCreationDialog(accountCreationDialogResult);
|
||||
|
||||
await ExecuteUIThreadTaskAsync(() => creationDialog.ShowDialogAsync(accountCreationCancellationTokenSource));
|
||||
await Task.Delay(500);
|
||||
|
||||
await ExecuteUIThread(() => creationDialog.State = AccountCreationDialogState.SigningIn);
|
||||
|
||||
customServerInformation = _specialImapProviderConfigResolver.GetServerInformation(createdAccount, accountCreationDialogResult)
|
||||
?? throw new AccountSetupCanceledException();
|
||||
|
||||
customServerInformation.Id = Guid.NewGuid();
|
||||
customServerInformation.AccountId = createdAccount.Id;
|
||||
|
||||
createdAccount.Address = accountCreationDialogResult.SpecialImapProviderDetails.Address;
|
||||
createdAccount.SenderName = accountCreationDialogResult.SpecialImapProviderDetails.SenderName;
|
||||
createdAccount.IsCalendarAccessGranted = customServerInformation.CalendarSupportMode != ImapCalendarSupportMode.Disabled;
|
||||
createdAccount.ServerInformation = customServerInformation;
|
||||
|
||||
await ValidateSpecialImapConnectivityAsync(customServerInformation).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
var completionSource = new TaskCompletionSource<ImapCalDavSetupResult>();
|
||||
var setupContext = ImapCalDavSettingsNavigationContext.CreateForCreateMode(accountCreationDialogResult, completionSource);
|
||||
|
||||
await ExecuteUIThread(() => Messenger.Send(new BreadcrumbNavigationRequested(
|
||||
Translator.ImapCalDavSettingsPage_TitleCreate,
|
||||
WinoPage.ImapCalDavSettingsPage,
|
||||
setupContext)));
|
||||
|
||||
var setupResult = await completionSource.Task.ConfigureAwait(false)
|
||||
?? throw new AccountSetupCanceledException();
|
||||
|
||||
customServerInformation = setupResult.ServerInformation ?? throw new AccountSetupCanceledException();
|
||||
customServerInformation.Id = Guid.NewGuid();
|
||||
customServerInformation.AccountId = createdAccount.Id;
|
||||
|
||||
createdAccount.Address = setupResult.EmailAddress;
|
||||
createdAccount.SenderName = setupResult.DisplayName;
|
||||
createdAccount.IsCalendarAccessGranted = setupResult.IsCalendarAccessGranted;
|
||||
createdAccount.ServerInformation = customServerInformation;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var accountCreationCancellationTokenSource = new CancellationTokenSource();
|
||||
creationDialog = MailDialogService.GetAccountCreationDialog(accountCreationDialogResult);
|
||||
|
||||
await ExecuteUIThreadTaskAsync(() => creationDialog.ShowDialogAsync(accountCreationCancellationTokenSource));
|
||||
await Task.Delay(500);
|
||||
|
||||
await ExecuteUIThread(() => creationDialog.State = AccountCreationDialogState.SigningIn);
|
||||
|
||||
// OAuth authentication is handled here.
|
||||
// Use SynchronizationManager to handle OAuth authentication.
|
||||
|
||||
var authTokenInfo = await SynchronizationManager.Instance.HandleAuthorizationAsync(
|
||||
accountCreationDialogResult.ProviderType,
|
||||
createdAccount,
|
||||
createdAccount.ProviderType == MailProviderType.Gmail);
|
||||
|
||||
bool creationCanceled = false;
|
||||
await ExecuteUIThread(() => creationCanceled = creationDialog.State == AccountCreationDialogState.Canceled);
|
||||
|
||||
if (creationCanceled)
|
||||
throw new AccountSetupCanceledException();
|
||||
|
||||
// Update account address with authenticated user information
|
||||
createdAccount.Address = authTokenInfo.AccountAddress;
|
||||
}
|
||||
|
||||
// Address is still doesn't have a value for API synchronizers.
|
||||
// It'll be synchronized with profile information.
|
||||
|
||||
await AccountService.CreateAccountAsync(createdAccount, customServerInformation);
|
||||
|
||||
// Local account has been created.
|
||||
|
||||
// Sync profile information if supported.
|
||||
if (createdAccount.IsProfileInfoSyncSupported)
|
||||
{
|
||||
// Start profile information synchronization.
|
||||
// It's only available for Outlook and Gmail synchronizers.
|
||||
|
||||
var profileSynchronizationResult = await SynchronizationManager.Instance.SynchronizeProfileAsync(createdAccount.Id);
|
||||
|
||||
if (profileSynchronizationResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeProfileInformation);
|
||||
|
||||
if (profileSynchronizationResult.ProfileInformation != null)
|
||||
{
|
||||
createdAccount.SenderName = profileSynchronizationResult.ProfileInformation.SenderName;
|
||||
createdAccount.Base64ProfilePictureData = profileSynchronizationResult.ProfileInformation.Base64ProfilePictureData;
|
||||
|
||||
if (!string.IsNullOrEmpty(profileSynchronizationResult.ProfileInformation.AccountAddress))
|
||||
{
|
||||
createdAccount.Address = profileSynchronizationResult.ProfileInformation.AccountAddress;
|
||||
}
|
||||
|
||||
await AccountService.UpdateProfileInformationAsync(createdAccount.Id, profileSynchronizationResult.ProfileInformation);
|
||||
}
|
||||
}
|
||||
|
||||
if (creationDialog != null)
|
||||
await ExecuteUIThread(() => creationDialog.State = AccountCreationDialogState.PreparingFolders);
|
||||
|
||||
var folderSynchronizationResult = await SynchronizationManager.Instance.SynchronizeFoldersAsync(createdAccount.Id);
|
||||
|
||||
if (folderSynchronizationResult == null || folderSynchronizationResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeFolders);
|
||||
|
||||
if (createdAccount.IsCalendarAccessGranted)
|
||||
{
|
||||
if (creationDialog != null)
|
||||
await ExecuteUIThread(() => creationDialog.State = AccountCreationDialogState.CalendarMetadataFetch);
|
||||
|
||||
var calendarMetadataSynchronizationResult = await SynchronizationManager.Instance.SynchronizeCalendarAsync(new CalendarSynchronizationOptions
|
||||
{
|
||||
AccountId = createdAccount.Id,
|
||||
Type = CalendarSynchronizationType.CalendarMetadata
|
||||
});
|
||||
|
||||
if (calendarMetadataSynchronizationResult == null || calendarMetadataSynchronizationResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeCalendarMetadata);
|
||||
}
|
||||
|
||||
// Sync aliases if supported.
|
||||
if (createdAccount.IsAliasSyncSupported)
|
||||
{
|
||||
// Try to synchronize aliases for the account.
|
||||
var aliasSynchronizationResult = await SynchronizationManager.Instance.SynchronizeAliasesAsync(createdAccount.Id);
|
||||
|
||||
if (aliasSynchronizationResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeAliases);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create root primary alias for the account.
|
||||
// This is only available for accounts that do not support alias synchronization.
|
||||
|
||||
await AccountService.CreateRootAliasAsync(createdAccount.Id, createdAccount.Address);
|
||||
}
|
||||
|
||||
if (creationDialog != null)
|
||||
{
|
||||
await ExecuteUIThread(() => creationDialog.Complete(false));
|
||||
creationDialogClosed = true;
|
||||
}
|
||||
|
||||
// Send changes to listeners.
|
||||
await ExecuteUIThread(() => ReportUIChange(new AccountCreatedMessage(createdAccount)));
|
||||
|
||||
// Notify success.
|
||||
await ExecuteUIThread(() => DialogService.InfoBarMessage(Translator.Info_AccountCreatedTitle, string.Format(Translator.Info_AccountCreatedMessage, createdAccount.Address), InfoBarMessageType.Success));
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (ex.Message.Contains(nameof(GmailServiceDisabledException)))
|
||||
{
|
||||
// For Google Workspace accounts, Gmail API might be disabled by the admin.
|
||||
// Wino can't continue synchronization in this case.
|
||||
// We must notify the user about this and prevent account creation.
|
||||
|
||||
await ExecuteUIThread(() => DialogService.InfoBarMessage(Translator.GmailServiceDisabled_Title, Translator.GmailServiceDisabled_Message, InfoBarMessageType.Error));
|
||||
|
||||
if (createdAccount != null)
|
||||
{
|
||||
await AccountService.DeleteAccountAsync(createdAccount);
|
||||
}
|
||||
}
|
||||
catch (AccountSetupCanceledException)
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
catch (Exception ex) when (ex.Message.Contains(nameof(AccountSetupCanceledException)))
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
catch (ImapClientPoolException testClientPoolException) when (testClientPoolException.CustomServerInformation != null)
|
||||
{
|
||||
var properties = testClientPoolException.CustomServerInformation.GetConnectionProperties();
|
||||
|
||||
properties.Add("ProtocolLog", testClientPoolException.ProtocolLog);
|
||||
properties.Add("DiagnosticId", PreferencesService.DiagnosticId);
|
||||
|
||||
_winoLogger.TrackEvent("IMAP Test Failed", properties);
|
||||
|
||||
await ExecuteUIThread(() => DialogService.InfoBarMessage(Translator.Info_AccountCreationFailedTitle, testClientPoolException.Message, InfoBarMessageType.Error));
|
||||
}
|
||||
catch (ImapClientPoolException clientPoolException) when (clientPoolException.InnerException != null)
|
||||
{
|
||||
await ExecuteUIThread(() => DialogService.InfoBarMessage(Translator.Info_AccountCreationFailedTitle, clientPoolException.InnerException.Message, InfoBarMessageType.Error));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Failed to create account.");
|
||||
|
||||
await ExecuteUIThread(() => DialogService.InfoBarMessage(Translator.Info_AccountCreationFailedTitle, ex.Message, InfoBarMessageType.Error));
|
||||
|
||||
// Delete account in case of failure.
|
||||
if (createdAccount != null)
|
||||
{
|
||||
await AccountService.DeleteAccountAsync(createdAccount);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (creationDialog != null && !creationDialogClosed)
|
||||
{
|
||||
bool isCanceled = false;
|
||||
await ExecuteUIThread(() => isCanceled = creationDialog.State == AccountCreationDialogState.Canceled);
|
||||
await ExecuteUIThread(() => creationDialog.Complete(isCanceled));
|
||||
}
|
||||
}
|
||||
Messenger.Send(new BreadcrumbNavigationRequested(Translator.WelcomeWizard_Step2Title, WinoPage.ProviderSelectionPage));
|
||||
}
|
||||
|
||||
public Task StartAddNewAccountAsync() => AddNewAccountAsync();
|
||||
|
||||
Reference in New Issue
Block a user