Add capability-first account and calendar setup flow
This commit is contained in:
@@ -17,6 +17,7 @@ using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Accounts;
|
||||
using Wino.Core.Domain.Models.Folders;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Domain.Models.Synchronization;
|
||||
using Wino.Core.Misc;
|
||||
using Wino.Core.Services;
|
||||
using Wino.Core.ViewModels.Data;
|
||||
@@ -96,8 +97,14 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
|
||||
[ObservableProperty]
|
||||
private bool isTaskbarBadgeEnabled;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial AccountCapabilityOption SelectedCapabilityOption { get; set; }
|
||||
|
||||
public bool IsFocusedInboxSupportedForAccount => Account != null && Account.Preferences.IsFocusedInboxEnabled != null;
|
||||
public bool IsImapServer => ServerInformation != null;
|
||||
public bool HasMailAccess => Account?.IsMailAccessGranted == true;
|
||||
public bool HasCalendarAccess => Account?.IsCalendarAccessGranted == true;
|
||||
public bool IsOAuthCapabilityEditable => Account?.ProviderType is MailProviderType.Outlook or MailProviderType.Gmail;
|
||||
public string ProviderIconPath => Account?.SpecialImapProvider != SpecialImapProvider.None
|
||||
? $"ms-appx:///Assets/Providers/{Account.SpecialImapProvider}.png"
|
||||
: $"ms-appx:///Assets/Providers/{Account?.ProviderType}.png";
|
||||
@@ -130,6 +137,13 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
|
||||
new ImapConnectionSecurityModel(Core.Domain.Enums.ImapConnectionSecurity.None, Translator.ImapConnectionSecurity_None)
|
||||
];
|
||||
|
||||
public List<AccountCapabilityOption> CapabilityOptions { get; } =
|
||||
[
|
||||
new(true, false, Translator.AccountCapability_MailOnly),
|
||||
new(false, true, Translator.AccountCapability_CalendarOnly),
|
||||
new(true, true, Translator.AccountCapability_MailAndCalendar)
|
||||
];
|
||||
|
||||
|
||||
public AccountDetailsPageViewModel(IMailDialogService dialogService,
|
||||
IAccountService accountService,
|
||||
@@ -262,6 +276,7 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
|
||||
AccountName = Account.Name;
|
||||
SenderName = Account.SenderName;
|
||||
ServerInformation = Account.ServerInformation;
|
||||
SelectedCapabilityOption = ResolveCapabilityOption(Account.IsMailAccessGranted, Account.IsCalendarAccessGranted);
|
||||
|
||||
IsFocusedInboxEnabled = Account.Preferences.IsFocusedInboxEnabled.GetValueOrDefault();
|
||||
AreNotificationsEnabled = Account.Preferences.IsNotificationsEnabled;
|
||||
@@ -288,7 +303,11 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
|
||||
SelectedOutgoingServerConnectionSecurityIndex = AvailableConnectionSecurities.FindIndex(a => a.ImapConnectionSecurity == ServerInformation.OutgoingServerSocketOption);
|
||||
}
|
||||
|
||||
SelectedTabIndex = _statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar ? 2 : 1;
|
||||
SelectedTabIndex = _statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar && HasCalendarAccess
|
||||
? 2
|
||||
: HasMailAccess
|
||||
? 1
|
||||
: 0;
|
||||
|
||||
var folderStructures = (await _folderService.GetFolderStructureForAccountAsync(Account.Id, true)).Folders;
|
||||
|
||||
@@ -382,11 +401,15 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
|
||||
|
||||
partial void OnAccountChanged(MailAccount value)
|
||||
{
|
||||
SelectedCapabilityOption = ResolveCapabilityOption(value?.IsMailAccessGranted == true, value?.IsCalendarAccessGranted == true);
|
||||
OnPropertyChanged(nameof(IsFocusedInboxSupportedForAccount));
|
||||
OnPropertyChanged(nameof(ProviderIconPath));
|
||||
OnPropertyChanged(nameof(Address));
|
||||
OnPropertyChanged(nameof(IsInitialSynchronizationSummaryVisible));
|
||||
OnPropertyChanged(nameof(InitialSynchronizationSummary));
|
||||
OnPropertyChanged(nameof(HasMailAccess));
|
||||
OnPropertyChanged(nameof(HasCalendarAccess));
|
||||
OnPropertyChanged(nameof(IsOAuthCapabilityEditable));
|
||||
}
|
||||
|
||||
protected override async void OnPropertyChanged(PropertyChangedEventArgs e)
|
||||
@@ -417,6 +440,21 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
|
||||
Account.Preferences.IsTaskbarBadgeEnabled = IsTaskbarBadgeEnabled;
|
||||
await _accountService.UpdateAccountAsync(Account);
|
||||
break;
|
||||
case nameof(SelectedCapabilityOption) when IsOAuthCapabilityEditable && SelectedCapabilityOption != null:
|
||||
if (Account.IsMailAccessGranted == SelectedCapabilityOption.IsMailAccessGranted &&
|
||||
Account.IsCalendarAccessGranted == SelectedCapabilityOption.IsCalendarAccessGranted)
|
||||
break;
|
||||
|
||||
try
|
||||
{
|
||||
await UpdateOAuthCapabilityAsync(SelectedCapabilityOption);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await ExecuteUIThread(() => SelectedCapabilityOption = ResolveCapabilityOption(Account.IsMailAccessGranted, Account.IsCalendarAccessGranted));
|
||||
_dialogService.InfoBarMessage(Translator.GeneralTitle_Error, ex.Message, InfoBarMessageType.Error);
|
||||
}
|
||||
break;
|
||||
case nameof(SelectedPrimaryCalendar) when SelectedPrimaryCalendar != null:
|
||||
foreach (var calendar in AccountCalendars)
|
||||
{
|
||||
@@ -427,6 +465,111 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private AccountCapabilityOption ResolveCapabilityOption(bool isMailAccessGranted, bool isCalendarAccessGranted)
|
||||
=> CapabilityOptions.First(option =>
|
||||
option.IsMailAccessGranted == isMailAccessGranted &&
|
||||
option.IsCalendarAccessGranted == isCalendarAccessGranted);
|
||||
|
||||
private async Task UpdateOAuthCapabilityAsync(AccountCapabilityOption selectedOption)
|
||||
{
|
||||
var previousMailAccess = Account.IsMailAccessGranted;
|
||||
var previousCalendarAccess = Account.IsCalendarAccessGranted;
|
||||
var requiresReauthorization = (selectedOption.IsMailAccessGranted && !previousMailAccess) ||
|
||||
(selectedOption.IsCalendarAccessGranted && !previousCalendarAccess);
|
||||
|
||||
try
|
||||
{
|
||||
if (requiresReauthorization)
|
||||
{
|
||||
Account.IsMailAccessGranted = selectedOption.IsMailAccessGranted;
|
||||
Account.IsCalendarAccessGranted = selectedOption.IsCalendarAccessGranted;
|
||||
|
||||
await SynchronizationManager.Instance.HandleAuthorizationAsync(
|
||||
Account.ProviderType,
|
||||
Account,
|
||||
Account.ProviderType == MailProviderType.Gmail);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Account.IsMailAccessGranted = previousMailAccess;
|
||||
Account.IsCalendarAccessGranted = previousCalendarAccess;
|
||||
throw;
|
||||
}
|
||||
|
||||
Account.IsMailAccessGranted = selectedOption.IsMailAccessGranted;
|
||||
Account.IsCalendarAccessGranted = selectedOption.IsCalendarAccessGranted;
|
||||
|
||||
await _accountService.UpdateAccountAsync(Account);
|
||||
|
||||
if (selectedOption.IsMailAccessGranted && !previousMailAccess)
|
||||
{
|
||||
await SynchronizationManager.Instance.SynchronizeProfileAsync(Account.Id);
|
||||
await SynchronizationManager.Instance.SynchronizeMailAsync(new MailSynchronizationOptions
|
||||
{
|
||||
AccountId = Account.Id,
|
||||
Type = MailSynchronizationType.FullFolders
|
||||
});
|
||||
|
||||
if (Account.ProviderType == MailProviderType.Outlook)
|
||||
{
|
||||
await SynchronizationManager.Instance.SynchronizeMailAsync(new MailSynchronizationOptions
|
||||
{
|
||||
AccountId = Account.Id,
|
||||
Type = MailSynchronizationType.Categories
|
||||
});
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Account.Address))
|
||||
{
|
||||
var aliases = await _accountService.GetAccountAliasesAsync(Account.Id);
|
||||
var hasRootAlias = aliases.Any(alias => alias.IsRootAlias);
|
||||
|
||||
if (!hasRootAlias)
|
||||
{
|
||||
await _accountService.CreateRootAliasAsync(Account.Id, Account.Address);
|
||||
}
|
||||
}
|
||||
|
||||
await SynchronizationManager.Instance.SynchronizeMailAsync(new MailSynchronizationOptions
|
||||
{
|
||||
AccountId = Account.Id,
|
||||
Type = MailSynchronizationType.Alias
|
||||
});
|
||||
}
|
||||
|
||||
if (selectedOption.IsCalendarAccessGranted && !previousCalendarAccess)
|
||||
{
|
||||
await SynchronizationManager.Instance.SynchronizeCalendarAsync(new CalendarSynchronizationOptions
|
||||
{
|
||||
AccountId = Account.Id,
|
||||
Type = CalendarSynchronizationType.CalendarMetadata
|
||||
});
|
||||
}
|
||||
|
||||
var refreshedAccount = await _accountService.GetAccountAsync(Account.Id);
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
Account = refreshedAccount;
|
||||
AccountName = refreshedAccount.Name;
|
||||
SenderName = refreshedAccount.SenderName;
|
||||
EnsureSelectedTabForCapabilities();
|
||||
});
|
||||
}
|
||||
|
||||
private void EnsureSelectedTabForCapabilities()
|
||||
{
|
||||
if (SelectedTabIndex == 1 && !HasMailAccess)
|
||||
{
|
||||
SelectedTabIndex = HasCalendarAccess ? 2 : 0;
|
||||
}
|
||||
else if (SelectedTabIndex == 2 && !HasCalendarAccess)
|
||||
{
|
||||
SelectedTabIndex = HasMailAccess ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AccountCalendarShowAsOption
|
||||
@@ -441,6 +584,20 @@ public sealed class AccountCalendarShowAsOption
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AccountCapabilityOption
|
||||
{
|
||||
public bool IsMailAccessGranted { get; }
|
||||
public bool IsCalendarAccessGranted { get; }
|
||||
public string DisplayText { get; }
|
||||
|
||||
public AccountCapabilityOption(bool isMailAccessGranted, bool isCalendarAccessGranted, string displayText)
|
||||
{
|
||||
IsMailAccessGranted = isMailAccessGranted;
|
||||
IsCalendarAccessGranted = isCalendarAccessGranted;
|
||||
DisplayText = displayText;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class AccountCalendarSettingsItemViewModel : ObservableObject
|
||||
{
|
||||
public AccountCalendar Calendar { get; }
|
||||
|
||||
@@ -71,6 +71,8 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
private void BuildSteps()
|
||||
{
|
||||
Steps.Clear();
|
||||
var shouldSetupMail = WizardContext.IsMailAccessEnabled;
|
||||
var shouldSetupCalendar = WizardContext.IsCalendarAccessEnabled;
|
||||
|
||||
if (WizardContext.IsOAuthProvider)
|
||||
{
|
||||
@@ -78,31 +80,47 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
{
|
||||
Title = string.Format(Translator.AccountSetup_Step_Authenticating, WizardContext.SelectedProvider.Name)
|
||||
});
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_FetchingProfile });
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SavingAccount });
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SyncingFolders });
|
||||
if (WizardContext.SelectedProvider.Type == MailProviderType.Outlook)
|
||||
if (shouldSetupMail)
|
||||
{
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SyncingCategories });
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_FetchingProfile });
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SyncingFolders });
|
||||
|
||||
if (WizardContext.SelectedProvider.Type == MailProviderType.Outlook)
|
||||
{
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SyncingCategories });
|
||||
}
|
||||
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SyncingAliases });
|
||||
}
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_FetchingCalendarMetadata });
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SyncingAliases });
|
||||
|
||||
if (shouldSetupCalendar)
|
||||
{
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_FetchingCalendarMetadata });
|
||||
}
|
||||
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_Finalizing });
|
||||
}
|
||||
else if (WizardContext.IsSpecialImapProvider)
|
||||
{
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_TestingMailAuth });
|
||||
if (shouldSetupMail)
|
||||
{
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_TestingMailAuth });
|
||||
}
|
||||
|
||||
if (WizardContext.CalendarSupportMode == ImapCalendarSupportMode.CalDav)
|
||||
if (shouldSetupCalendar && WizardContext.CalendarSupportMode == ImapCalendarSupportMode.CalDav)
|
||||
{
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_DiscoveringCalDav });
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_TestingCalendarAuth });
|
||||
}
|
||||
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SavingAccount });
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SyncingFolders });
|
||||
if (shouldSetupMail)
|
||||
{
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SyncingFolders });
|
||||
}
|
||||
|
||||
if (WizardContext.CalendarSupportMode != ImapCalendarSupportMode.Disabled)
|
||||
if (shouldSetupCalendar && WizardContext.CalendarSupportMode != ImapCalendarSupportMode.Disabled)
|
||||
{
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_FetchingCalendarMetadata });
|
||||
}
|
||||
@@ -112,7 +130,10 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
else // Generic IMAP
|
||||
{
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SavingAccount });
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SyncingFolders });
|
||||
if (shouldSetupMail)
|
||||
{
|
||||
Steps.Add(new AccountSetupStepModel { Title = Translator.AccountSetup_Step_SyncingFolders });
|
||||
}
|
||||
|
||||
var setupResult = WizardContext.ImapCalDavSetupResult;
|
||||
if (setupResult?.IsCalendarAccessGranted == true &&
|
||||
@@ -186,7 +207,8 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
AccountColorHex = WizardContext.AccountColorHex,
|
||||
CreatedAt = accountCreatedAt,
|
||||
InitialSynchronizationRange = WizardContext.SelectedInitialSynchronizationRange,
|
||||
IsCalendarAccessGranted = true
|
||||
IsMailAccessGranted = WizardContext.IsMailAccessEnabled,
|
||||
IsCalendarAccessGranted = WizardContext.IsCalendarAccessEnabled
|
||||
};
|
||||
|
||||
if (WizardContext.IsOAuthProvider)
|
||||
@@ -208,50 +230,53 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
_dbWritten = true;
|
||||
SetCurrentStepSucceeded();
|
||||
|
||||
// Step: Profile
|
||||
SetStepInProgress(Translator.AccountSetup_Step_FetchingProfile);
|
||||
var profileResult = await SynchronizationManager.Instance.SynchronizeProfileAsync(_createdAccount.Id);
|
||||
if (profileResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeProfileInformation);
|
||||
|
||||
if (profileResult.ProfileInformation != null)
|
||||
if (_createdAccount.IsMailAccessGranted)
|
||||
{
|
||||
_createdAccount.SenderName = profileResult.ProfileInformation.SenderName;
|
||||
_createdAccount.Base64ProfilePictureData = profileResult.ProfileInformation.Base64ProfilePictureData;
|
||||
// Step: Profile
|
||||
SetStepInProgress(Translator.AccountSetup_Step_FetchingProfile);
|
||||
var profileResult = await SynchronizationManager.Instance.SynchronizeProfileAsync(_createdAccount.Id);
|
||||
if (profileResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeProfileInformation);
|
||||
|
||||
if (!string.IsNullOrEmpty(profileResult.ProfileInformation.AccountAddress))
|
||||
if (profileResult.ProfileInformation != null)
|
||||
{
|
||||
if (await _accountService.AccountAddressExistsAsync(profileResult.ProfileInformation.AccountAddress, _createdAccount.Id))
|
||||
throw new InvalidOperationException(Translator.DialogMessage_AccountAddressExistsMessage);
|
||||
_createdAccount.SenderName = profileResult.ProfileInformation.SenderName;
|
||||
_createdAccount.Base64ProfilePictureData = profileResult.ProfileInformation.Base64ProfilePictureData;
|
||||
|
||||
_createdAccount.Address = profileResult.ProfileInformation.AccountAddress;
|
||||
if (!string.IsNullOrEmpty(profileResult.ProfileInformation.AccountAddress))
|
||||
{
|
||||
if (await _accountService.AccountAddressExistsAsync(profileResult.ProfileInformation.AccountAddress, _createdAccount.Id))
|
||||
throw new InvalidOperationException(Translator.DialogMessage_AccountAddressExistsMessage);
|
||||
|
||||
_createdAccount.Address = profileResult.ProfileInformation.AccountAddress;
|
||||
}
|
||||
|
||||
await _accountService.UpdateProfileInformationAsync(_createdAccount.Id, profileResult.ProfileInformation);
|
||||
}
|
||||
|
||||
await _accountService.UpdateProfileInformationAsync(_createdAccount.Id, profileResult.ProfileInformation);
|
||||
}
|
||||
SetCurrentStepSucceeded();
|
||||
|
||||
// Step: Folders
|
||||
SetStepInProgress(Translator.AccountSetup_Step_SyncingFolders);
|
||||
var folderResult = await SynchronizationManager.Instance.SynchronizeFoldersAsync(_createdAccount.Id);
|
||||
if (folderResult == null || folderResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeFolders);
|
||||
SetCurrentStepSucceeded();
|
||||
|
||||
// Step: Categories
|
||||
if (_createdAccount.IsCategorySyncSupported)
|
||||
{
|
||||
SetStepInProgress(Translator.AccountSetup_Step_SyncingCategories);
|
||||
var categoryResult = await SynchronizationManager.Instance.SynchronizeCategoriesAsync(_createdAccount.Id);
|
||||
if (categoryResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeCategories);
|
||||
SetCurrentStepSucceeded();
|
||||
|
||||
// Step: Folders
|
||||
SetStepInProgress(Translator.AccountSetup_Step_SyncingFolders);
|
||||
var folderResult = await SynchronizationManager.Instance.SynchronizeFoldersAsync(_createdAccount.Id);
|
||||
if (folderResult == null || folderResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeFolders);
|
||||
SetCurrentStepSucceeded();
|
||||
|
||||
// Step: Categories
|
||||
if (_createdAccount.IsCategorySyncSupported)
|
||||
{
|
||||
SetStepInProgress(Translator.AccountSetup_Step_SyncingCategories);
|
||||
var categoryResult = await SynchronizationManager.Instance.SynchronizeCategoriesAsync(_createdAccount.Id);
|
||||
if (categoryResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeCategories);
|
||||
SetCurrentStepSucceeded();
|
||||
}
|
||||
}
|
||||
|
||||
// Step: Calendar metadata
|
||||
SetStepInProgress(Translator.AccountSetup_Step_FetchingCalendarMetadata);
|
||||
if (_createdAccount.IsCalendarAccessGranted)
|
||||
{
|
||||
SetStepInProgress(Translator.AccountSetup_Step_FetchingCalendarMetadata);
|
||||
var calResult = await SynchronizationManager.Instance.SynchronizeCalendarAsync(new CalendarSynchronizationOptions
|
||||
{
|
||||
AccountId = _createdAccount.Id,
|
||||
@@ -259,22 +284,25 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
});
|
||||
if (calResult == null || calResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeCalendarMetadata);
|
||||
SetCurrentStepSucceeded();
|
||||
}
|
||||
SetCurrentStepSucceeded();
|
||||
|
||||
// Step: Aliases
|
||||
SetStepInProgress(Translator.AccountSetup_Step_SyncingAliases);
|
||||
if (_createdAccount.IsAliasSyncSupported)
|
||||
if (_createdAccount.IsMailAccessGranted)
|
||||
{
|
||||
var aliasResult = await SynchronizationManager.Instance.SynchronizeAliasesAsync(_createdAccount.Id);
|
||||
if (aliasResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeAliases);
|
||||
SetStepInProgress(Translator.AccountSetup_Step_SyncingAliases);
|
||||
if (_createdAccount.IsAliasSyncSupported)
|
||||
{
|
||||
var aliasResult = await SynchronizationManager.Instance.SynchronizeAliasesAsync(_createdAccount.Id);
|
||||
if (aliasResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeAliases);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _accountService.CreateRootAliasAsync(_createdAccount.Id, _createdAccount.Address);
|
||||
}
|
||||
SetCurrentStepSucceeded();
|
||||
}
|
||||
else
|
||||
{
|
||||
await _accountService.CreateRootAliasAsync(_createdAccount.Id, _createdAccount.Address);
|
||||
}
|
||||
SetCurrentStepSucceeded();
|
||||
}
|
||||
else if (WizardContext.IsSpecialImapProvider)
|
||||
{
|
||||
@@ -288,13 +316,17 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
|
||||
_createdAccount.Address = WizardContext.EmailAddress;
|
||||
_createdAccount.SenderName = WizardContext.DisplayName;
|
||||
_createdAccount.IsMailAccessGranted = dialogResult.IsMailAccessGranted;
|
||||
_createdAccount.IsCalendarAccessGranted = customServerInformation.CalendarSupportMode != ImapCalendarSupportMode.Disabled;
|
||||
_createdAccount.ServerInformation = customServerInformation;
|
||||
|
||||
// Step: Test IMAP
|
||||
SetStepInProgress(Translator.AccountSetup_Step_TestingMailAuth);
|
||||
await ValidateImapConnectivityAsync(customServerInformation);
|
||||
SetCurrentStepSucceeded();
|
||||
if (_createdAccount.IsMailAccessGranted)
|
||||
{
|
||||
// Step: Test IMAP
|
||||
SetStepInProgress(Translator.AccountSetup_Step_TestingMailAuth);
|
||||
await ValidateImapConnectivityAsync(customServerInformation);
|
||||
SetCurrentStepSucceeded();
|
||||
}
|
||||
|
||||
// Step: CalDAV discovery and testing (if applicable)
|
||||
if (customServerInformation.CalendarSupportMode == ImapCalendarSupportMode.CalDav)
|
||||
@@ -313,12 +345,15 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
_dbWritten = true;
|
||||
SetCurrentStepSucceeded();
|
||||
|
||||
// Step: Folders
|
||||
SetStepInProgress(Translator.AccountSetup_Step_SyncingFolders);
|
||||
var folderResult = await SynchronizationManager.Instance.SynchronizeFoldersAsync(_createdAccount.Id);
|
||||
if (folderResult == null || folderResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeFolders);
|
||||
SetCurrentStepSucceeded();
|
||||
if (_createdAccount.IsMailAccessGranted)
|
||||
{
|
||||
// Step: Folders
|
||||
SetStepInProgress(Translator.AccountSetup_Step_SyncingFolders);
|
||||
var folderResult = await SynchronizationManager.Instance.SynchronizeFoldersAsync(_createdAccount.Id);
|
||||
if (folderResult == null || folderResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeFolders);
|
||||
SetCurrentStepSucceeded();
|
||||
}
|
||||
|
||||
// Step: Calendar metadata (if not disabled)
|
||||
if (_createdAccount.IsCalendarAccessGranted)
|
||||
@@ -334,8 +369,10 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
SetCurrentStepSucceeded();
|
||||
}
|
||||
|
||||
// Aliases for IMAP
|
||||
await _accountService.CreateRootAliasAsync(_createdAccount.Id, _createdAccount.Address);
|
||||
if (_createdAccount.IsMailAccessGranted)
|
||||
{
|
||||
await _accountService.CreateRootAliasAsync(_createdAccount.Id, _createdAccount.Address);
|
||||
}
|
||||
}
|
||||
else // Generic IMAP
|
||||
{
|
||||
@@ -350,6 +387,7 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
|
||||
_createdAccount.Address = setupResult.EmailAddress;
|
||||
_createdAccount.SenderName = setupResult.DisplayName;
|
||||
_createdAccount.IsMailAccessGranted = setupResult.IsMailAccessGranted;
|
||||
_createdAccount.IsCalendarAccessGranted = setupResult.IsCalendarAccessGranted;
|
||||
_createdAccount.ServerInformation = customServerInformation;
|
||||
|
||||
@@ -359,12 +397,15 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
_dbWritten = true;
|
||||
SetCurrentStepSucceeded();
|
||||
|
||||
// Step: Folders
|
||||
SetStepInProgress(Translator.AccountSetup_Step_SyncingFolders);
|
||||
var folderResult = await SynchronizationManager.Instance.SynchronizeFoldersAsync(_createdAccount.Id);
|
||||
if (folderResult == null || folderResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeFolders);
|
||||
SetCurrentStepSucceeded();
|
||||
if (_createdAccount.IsMailAccessGranted)
|
||||
{
|
||||
// Step: Folders
|
||||
SetStepInProgress(Translator.AccountSetup_Step_SyncingFolders);
|
||||
var folderResult = await SynchronizationManager.Instance.SynchronizeFoldersAsync(_createdAccount.Id);
|
||||
if (folderResult == null || folderResult.CompletedState != SynchronizationCompletedState.Success)
|
||||
throw new Exception(Translator.Exception_FailedToSynchronizeFolders);
|
||||
SetCurrentStepSucceeded();
|
||||
}
|
||||
|
||||
// Step: CalDAV (if applicable)
|
||||
if (setupResult.IsCalendarAccessGranted &&
|
||||
@@ -392,8 +433,10 @@ public partial class AccountSetupProgressPageViewModel : MailBaseViewModel
|
||||
SetCurrentStepSucceeded();
|
||||
}
|
||||
|
||||
// Aliases for IMAP
|
||||
await _accountService.CreateRootAliasAsync(_createdAccount.Id, _createdAccount.Address);
|
||||
if (_createdAccount.IsMailAccessGranted)
|
||||
{
|
||||
await _accountService.CreateRootAliasAsync(_createdAccount.Id, _createdAccount.Address);
|
||||
}
|
||||
}
|
||||
|
||||
// Step: Finalizing
|
||||
|
||||
@@ -61,6 +61,7 @@ public sealed class ImapCalDavSetupResult
|
||||
{
|
||||
public string DisplayName { get; init; }
|
||||
public string EmailAddress { get; init; }
|
||||
public bool IsMailAccessGranted { get; init; }
|
||||
public bool IsCalendarAccessGranted { get; init; }
|
||||
public CustomServerInformation ServerInformation { get; init; }
|
||||
}
|
||||
|
||||
@@ -21,6 +21,12 @@ public partial class WelcomeWizardContext : ObservableObject
|
||||
[ObservableProperty]
|
||||
public partial InitialSynchronizationRange SelectedInitialSynchronizationRange { get; set; } = InitialSynchronizationRange.SixMonths;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsMailAccessEnabled { get; set; } = true;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsCalendarAccessEnabled { get; set; } = true;
|
||||
|
||||
// Special IMAP fields (iCloud/Yahoo)
|
||||
[ObservableProperty]
|
||||
public partial string DisplayName { get; set; }
|
||||
@@ -66,7 +72,9 @@ public partial class WelcomeWizardContext : ObservableObject
|
||||
AccountName,
|
||||
BuildSpecialImapProviderDetails(),
|
||||
AccountColorHex,
|
||||
SelectedInitialSynchronizationRange);
|
||||
SelectedInitialSynchronizationRange,
|
||||
IsMailAccessEnabled,
|
||||
IsCalendarAccessEnabled);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
@@ -75,6 +83,8 @@ public partial class WelcomeWizardContext : ObservableObject
|
||||
AccountName = null;
|
||||
AccountColorHex = null;
|
||||
SelectedInitialSynchronizationRange = InitialSynchronizationRange.SixMonths;
|
||||
IsMailAccessEnabled = true;
|
||||
IsCalendarAccessEnabled = true;
|
||||
DisplayName = null;
|
||||
EmailAddress = null;
|
||||
AppSpecificPassword = null;
|
||||
|
||||
@@ -1,9 +1,50 @@
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.ViewModels;
|
||||
|
||||
namespace Wino.Mail.ViewModels;
|
||||
|
||||
public partial class IdlePageViewModel : CoreBaseViewModel
|
||||
{
|
||||
public IdlePageViewModel(IMailDialogService dialogService) { }
|
||||
public const string MailEmptyStateParameter = "mail-empty-state";
|
||||
|
||||
private readonly INavigationService _navigationService;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsMailEmptyStateVisible { get; set; }
|
||||
|
||||
public string MailEmptyStateTitle => Translator.MailEmptyState_Title;
|
||||
public string MailEmptyStateMessage => Translator.MailEmptyState_Message;
|
||||
public string AddAccountText => Translator.MailEmptyState_AddAccount;
|
||||
public string ManageAccountsText => Translator.MailEmptyState_ManageAccounts;
|
||||
|
||||
public IdlePageViewModel(IMailDialogService dialogService, INavigationService navigationService)
|
||||
{
|
||||
_navigationService = navigationService;
|
||||
}
|
||||
|
||||
public override void OnNavigatedTo(NavigationMode mode, object parameters)
|
||||
{
|
||||
base.OnNavigatedTo(mode, parameters);
|
||||
IsMailEmptyStateVisible = string.Equals(parameters as string, MailEmptyStateParameter, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void AddAccount()
|
||||
=> _navigationService.Navigate(
|
||||
WinoPage.SettingsPage,
|
||||
ProviderSelectionNavigationContext.CreateForSettingsAddAccount(),
|
||||
NavigationReferenceFrame.ShellFrame);
|
||||
|
||||
[RelayCommand]
|
||||
private void ManageAccounts()
|
||||
=> _navigationService.Navigate(
|
||||
WinoPage.SettingsPage,
|
||||
WinoPage.ManageAccountsPage,
|
||||
NavigationReferenceFrame.ShellFrame);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,12 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
[ObservableProperty]
|
||||
private string password = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(IsMailSettingsVisible))]
|
||||
[NotifyPropertyChangedFor(nameof(IsMailPasswordInputVisible))]
|
||||
[NotifyPropertyChangedFor(nameof(IsMailActionsVisible))]
|
||||
private bool isMailSupportEnabled = true;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(IsCalendarModeSelectionVisible))]
|
||||
[NotifyPropertyChangedFor(nameof(IsCalDavSettingsVisible))]
|
||||
@@ -141,6 +147,9 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
public bool HasProviderHint => !string.IsNullOrWhiteSpace(ProviderHint);
|
||||
public bool IsBasicSetupSelected => SelectedSetupTabIndex == 0;
|
||||
public bool IsAdvancedSetupSelected => SelectedSetupTabIndex == 1;
|
||||
public bool IsMailSettingsVisible => IsMailSupportEnabled;
|
||||
public bool IsMailPasswordInputVisible => IsMailSupportEnabled;
|
||||
public bool IsMailActionsVisible => IsMailSupportEnabled;
|
||||
public bool IsCalendarModeSelectionVisible => IsCalendarSupportEnabled;
|
||||
public bool IsCalDavSettingsVisible => IsCalendarSupportEnabled && SelectedCalendarSupportMode == ImapCalendarSupportMode.CalDav;
|
||||
public bool IsLocalCalendarModeSelected => IsCalendarSupportEnabled && SelectedCalendarSupportMode == ImapCalendarSupportMode.LocalOnly;
|
||||
@@ -152,6 +161,7 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
public string EmailAddressHeaderText => Translator.IMAPSetupDialog_MailAddress;
|
||||
public string EmailAddressPlaceholderText => Translator.IMAPSetupDialog_MailAddressPlaceholder;
|
||||
public string PasswordHeaderText => Translator.IMAPSetupDialog_Password;
|
||||
public string EnableMailSupportText => Translator.ProviderSelection_UseForMail;
|
||||
public string EnableCalendarSupportText => Translator.ImapCalDavSettingsPage_EnableCalendarSupport;
|
||||
public string AutoDiscoverButtonText => Translator.ImapCalDavSettingsPage_AutoDiscoverButton;
|
||||
public string BasicTabText => Translator.ImapCalDavSettingsPage_BasicTab;
|
||||
@@ -342,6 +352,7 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
{
|
||||
try
|
||||
{
|
||||
ValidateCapabilitySelection();
|
||||
await EnsureImapSettingsPreparedAsync().ConfigureAwait(false);
|
||||
var serverInformation = BuildServerInformation();
|
||||
|
||||
@@ -401,6 +412,7 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
{
|
||||
try
|
||||
{
|
||||
ValidateCapabilitySelection();
|
||||
await EnsureImapSettingsPreparedAsync();
|
||||
|
||||
var serverInformation = BuildServerInformation();
|
||||
@@ -416,8 +428,15 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
if (!await ValidateAccountUniquenessAsync(excludedAccountId))
|
||||
return;
|
||||
|
||||
await ValidateImapConnectivityAsync(serverInformation);
|
||||
IsImapValidationSucceeded = true;
|
||||
if (IsMailSupportEnabled)
|
||||
{
|
||||
await ValidateImapConnectivityAsync(serverInformation);
|
||||
IsImapValidationSucceeded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsImapValidationSucceeded = false;
|
||||
}
|
||||
|
||||
if (serverInformation.CalendarSupportMode == ImapCalendarSupportMode.CalDav)
|
||||
{
|
||||
@@ -485,6 +504,7 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
{
|
||||
DisplayName = DisplayName.Trim(),
|
||||
EmailAddress = EmailAddress.Trim(),
|
||||
IsMailAccessGranted = IsMailSupportEnabled,
|
||||
IsCalendarAccessGranted = serverInformation.CalendarSupportMode != ImapCalendarSupportMode.Disabled,
|
||||
ServerInformation = serverInformation
|
||||
};
|
||||
@@ -511,6 +531,14 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnIsMailSupportEnabledChanged(bool value)
|
||||
{
|
||||
if (!value)
|
||||
{
|
||||
IsImapValidationSucceeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnSelectedCalendarSupportModeChanged(ImapCalendarSupportMode value)
|
||||
{
|
||||
if (value == ImapCalendarSupportMode.LocalOnly && !_localOnlyInfoShown)
|
||||
@@ -562,6 +590,7 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
ApplyProviderHint(_editingSpecialImapProvider);
|
||||
|
||||
ApplyServerInformation(account.ServerInformation);
|
||||
IsMailSupportEnabled = account.IsMailAccessGranted;
|
||||
|
||||
if (account.ServerInformation != null)
|
||||
{
|
||||
@@ -588,8 +617,10 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
if (!string.IsNullOrWhiteSpace(accountCreationDialogResult?.SpecialImapProviderDetails?.SenderName))
|
||||
DisplayName = accountCreationDialogResult.SpecialImapProviderDetails.SenderName;
|
||||
|
||||
IsCalendarSupportEnabled = true;
|
||||
SelectedCalendarSupportMode = ImapCalendarSupportMode.CalDav;
|
||||
IsMailSupportEnabled = accountCreationDialogResult?.IsMailAccessGranted != false;
|
||||
IsCalendarSupportEnabled = accountCreationDialogResult?.IsCalendarAccessGranted == true;
|
||||
SelectedCalendarSupportMode = accountCreationDialogResult?.SpecialImapProviderDetails?.CalendarSupportMode
|
||||
?? (IsCalendarSupportEnabled ? ImapCalendarSupportMode.CalDav : ImapCalendarSupportMode.Disabled);
|
||||
|
||||
var specialProvider = accountCreationDialogResult?.SpecialImapProviderDetails?.SpecialImapProvider ?? SpecialImapProvider.None;
|
||||
_editingSpecialImapProvider = specialProvider;
|
||||
@@ -737,6 +768,9 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
|
||||
private async Task EnsureImapSettingsPreparedAsync()
|
||||
{
|
||||
if (!IsMailSupportEnabled)
|
||||
return;
|
||||
|
||||
if (HasCompleteImapSettings())
|
||||
return;
|
||||
|
||||
@@ -847,6 +881,7 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
{
|
||||
DisplayName = DisplayName.Trim(),
|
||||
EmailAddress = EmailAddress.Trim(),
|
||||
IsMailAccessGranted = IsMailSupportEnabled,
|
||||
IsCalendarAccessGranted = serverInformation.CalendarSupportMode != ImapCalendarSupportMode.Disabled,
|
||||
ServerInformation = serverInformation
|
||||
});
|
||||
@@ -863,7 +898,9 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
|
||||
private async Task<bool> ValidateAccountUniquenessAsync(Guid? excludedAccountId)
|
||||
{
|
||||
var accountName = (_pageMode == ImapCalDavSettingsPageMode.Create || _pageMode == ImapCalDavSettingsPageMode.Wizard)
|
||||
var accountName = (_pageMode == ImapCalDavSettingsPageMode.Create
|
||||
|| _pageMode == ImapCalDavSettingsPageMode.Wizard
|
||||
|| _pageMode == ImapCalDavSettingsPageMode.AddAccount)
|
||||
? _accountCreationContext?.AccountName
|
||||
: null;
|
||||
|
||||
@@ -889,6 +926,15 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ValidateCapabilitySelection(bool isMailEnabled, bool isCalendarEnabled)
|
||||
{
|
||||
if (!isMailEnabled && !isCalendarEnabled)
|
||||
throw new InvalidOperationException(Translator.ProviderSelection_CapabilityValidationMessage);
|
||||
}
|
||||
|
||||
private void ValidateCapabilitySelection()
|
||||
=> ValidateCapabilitySelection(IsMailSupportEnabled, IsCalendarSupportEnabled);
|
||||
|
||||
private async Task SaveEditFlowAsync(CustomServerInformation serverInformation)
|
||||
{
|
||||
var account = await _accountService.GetAccountAsync(_editingAccountId);
|
||||
@@ -897,6 +943,7 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
|
||||
account.SenderName = DisplayName.Trim();
|
||||
account.Address = EmailAddress.Trim();
|
||||
account.IsMailAccessGranted = IsMailSupportEnabled;
|
||||
account.IsCalendarAccessGranted = serverInformation.CalendarSupportMode != ImapCalendarSupportMode.Disabled;
|
||||
|
||||
serverInformation.Id = account.ServerInformation?.Id ?? Guid.NewGuid();
|
||||
@@ -908,11 +955,14 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
await _accountService.UpdateAccountCustomServerInformationAsync(serverInformation);
|
||||
await _accountService.UpdateAccountAsync(account);
|
||||
|
||||
Messenger.Send(new NewMailSynchronizationRequested(new MailSynchronizationOptions
|
||||
if (account.IsMailAccessGranted)
|
||||
{
|
||||
AccountId = account.Id,
|
||||
Type = MailSynchronizationType.FullFolders
|
||||
}));
|
||||
Messenger.Send(new NewMailSynchronizationRequested(new MailSynchronizationOptions
|
||||
{
|
||||
AccountId = account.Id,
|
||||
Type = MailSynchronizationType.FullFolders
|
||||
}));
|
||||
}
|
||||
|
||||
if (account.IsCalendarAccessGranted)
|
||||
{
|
||||
@@ -1007,6 +1057,9 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
|
||||
private void ValidateImapSettings(CustomServerInformation serverInformation)
|
||||
{
|
||||
if (!IsMailSupportEnabled)
|
||||
return;
|
||||
|
||||
ValidateIdentitySettings();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(serverInformation.IncomingServer))
|
||||
@@ -1075,7 +1128,7 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
|
||||
private bool TryApplyKnownProviderSettingsIfNeeded(bool requireCompleteImapSettings, bool requireCompleteCalDavSettings)
|
||||
{
|
||||
var needsImapSettings = requireCompleteImapSettings && !HasCompleteImapSettings();
|
||||
var needsImapSettings = IsMailSupportEnabled && requireCompleteImapSettings && !HasCompleteImapSettings();
|
||||
var needsCalDavSettings = requireCompleteCalDavSettings
|
||||
&& IsCalendarSupportEnabled
|
||||
&& SelectedCalendarSupportMode == ImapCalendarSupportMode.CalDav
|
||||
@@ -1114,6 +1167,7 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
SenderName = DisplayName.Trim(),
|
||||
ProviderType = MailProviderType.IMAP4,
|
||||
SpecialImapProvider = _editingSpecialImapProvider,
|
||||
IsMailAccessGranted = IsMailSupportEnabled,
|
||||
IsCalendarAccessGranted = mode != ImapCalendarSupportMode.Disabled
|
||||
},
|
||||
new AccountCreationDialogResult(
|
||||
@@ -1121,7 +1175,9 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
DisplayName.Trim(),
|
||||
providerDetails,
|
||||
string.Empty,
|
||||
_wizardContext.SelectedInitialSynchronizationRange));
|
||||
_wizardContext.SelectedInitialSynchronizationRange,
|
||||
IsMailSupportEnabled,
|
||||
mode != ImapCalendarSupportMode.Disabled));
|
||||
|
||||
if (serverInformation == null)
|
||||
return false;
|
||||
@@ -1158,7 +1214,8 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
&& !string.IsNullOrWhiteSpace(CalDavPassword));
|
||||
|
||||
private bool HasCompleteImapSettings()
|
||||
=> !string.IsNullOrWhiteSpace(IncomingServer)
|
||||
=> !IsMailSupportEnabled
|
||||
|| (!string.IsNullOrWhiteSpace(IncomingServer)
|
||||
&& !string.IsNullOrWhiteSpace(IncomingServerPort)
|
||||
&& !string.IsNullOrWhiteSpace(IncomingServerUsername)
|
||||
&& !string.IsNullOrWhiteSpace(IncomingServerPassword)
|
||||
@@ -1167,7 +1224,7 @@ public partial class ImapCalDavSettingsPageViewModel : MailBaseViewModel
|
||||
&& !string.IsNullOrWhiteSpace(OutgoingServerUsername)
|
||||
&& !string.IsNullOrWhiteSpace(OutgoingServerPassword)
|
||||
&& IsValidPort(IncomingServerPort)
|
||||
&& IsValidPort(OutgoingServerPort);
|
||||
&& IsValidPort(OutgoingServerPort));
|
||||
|
||||
private int FindAuthenticationMethodIndex(ImapAuthenticationMethod method)
|
||||
{
|
||||
|
||||
@@ -46,6 +46,8 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
IRecipient<AccountRemovedMessage>,
|
||||
IRecipient<AccountUpdatedMessage>
|
||||
{
|
||||
private const string MailEmptyStateNavigationParameter = IdlePageViewModel.MailEmptyStateParameter;
|
||||
|
||||
#region Menu Items
|
||||
|
||||
[ObservableProperty]
|
||||
@@ -188,7 +190,7 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
// First clear all account menu items.
|
||||
MenuItems.RemoveRange(MenuItems.Where(a => a is IAccountMenuItem));
|
||||
|
||||
var accounts = await _accountService.GetAccountsAsync().ConfigureAwait(false);
|
||||
var accounts = await GetMailEnabledAccountsAsync().ConfigureAwait(false);
|
||||
|
||||
List<Guid> initializedAccountIds = new();
|
||||
|
||||
@@ -373,7 +375,7 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
private async Task ForceAllAccountSynchronizationsAsync()
|
||||
{
|
||||
// Run Inbox synchronization for all accounts on startup.
|
||||
var accounts = await _accountService.GetAccountsAsync();
|
||||
var accounts = await GetMailEnabledAccountsAsync().ConfigureAwait(false);
|
||||
|
||||
foreach (var account in accounts)
|
||||
{
|
||||
@@ -442,6 +444,9 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
|
||||
private async Task ProcessLaunchDefaultAsync()
|
||||
{
|
||||
if (await NavigateToMailEmptyStateIfNeededAsync().ConfigureAwait(false))
|
||||
return;
|
||||
|
||||
if (PreferencesService.StartupEntityId == null)
|
||||
{
|
||||
NavigateToWelcomeWizard();
|
||||
@@ -468,8 +473,16 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback to the welcome wizard if startup entity is not found.
|
||||
NavigateToWelcomeWizard();
|
||||
var firstMailAccountMenuItem = MenuItems.FirstOrDefault(a => a is IAccountMenuItem) as IAccountMenuItem;
|
||||
if (firstMailAccountMenuItem != null)
|
||||
{
|
||||
firstMailAccountMenuItem.Expand();
|
||||
await ChangeLoadedAccountAsync(firstMailAccountMenuItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigateToWelcomeWizard();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -947,6 +960,11 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
operationAccount = selectedFolderMenuItem.ParentAccount;
|
||||
}
|
||||
|
||||
if (operationAccount?.IsMailAccessGranted == false)
|
||||
{
|
||||
operationAccount = null;
|
||||
}
|
||||
|
||||
// We couldn't find any account so far.
|
||||
// If there is only 1 account to use, use it. If not,
|
||||
// send a message for flyout so user can pick from it.
|
||||
@@ -956,7 +974,7 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
// No selected account.
|
||||
// List all accounts and let user pick one.
|
||||
|
||||
var accounts = await _accountService.GetAccountsAsync();
|
||||
var accounts = await GetMailEnabledAccountsAsync().ConfigureAwait(false);
|
||||
|
||||
if (!accounts.Any())
|
||||
{
|
||||
@@ -1081,7 +1099,7 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
|
||||
public async void Receive(MailtoProtocolMessageRequested message)
|
||||
{
|
||||
var accounts = await _accountService.GetAccountsAsync();
|
||||
var accounts = await GetMailEnabledAccountsAsync().ConfigureAwait(false);
|
||||
|
||||
MailAccount targetAccount = null;
|
||||
|
||||
@@ -1114,7 +1132,7 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
if (shareRequest?.Files == null || shareRequest.Files.Count == 0)
|
||||
return;
|
||||
|
||||
var accounts = await _accountService.GetAccountsAsync();
|
||||
var accounts = await GetMailEnabledAccountsAsync().ConfigureAwait(false);
|
||||
|
||||
if (!accounts.Any())
|
||||
return;
|
||||
@@ -1188,7 +1206,10 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
else
|
||||
{
|
||||
await ExecuteUIThread(() => SelectedMenuItem = null);
|
||||
NavigateToWelcomeWizard();
|
||||
if (!await NavigateToMailEmptyStateIfNeededAsync().ConfigureAwait(false))
|
||||
{
|
||||
NavigateToWelcomeWizard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1199,6 +1220,37 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
NavigationReferenceFrame.ShellFrame,
|
||||
NavigationTransitionType.None);
|
||||
|
||||
private Task<List<MailAccount>> GetMailEnabledAccountsAsync()
|
||||
=> GetAccountsByCapabilityAsync(requireMail: true);
|
||||
|
||||
private async Task<List<MailAccount>> GetAccountsByCapabilityAsync(bool requireMail = false, bool requireCalendar = false)
|
||||
{
|
||||
var accounts = await _accountService.GetAccountsAsync().ConfigureAwait(false);
|
||||
|
||||
return accounts
|
||||
.Where(account => (!requireMail || account.IsMailAccessGranted) &&
|
||||
(!requireCalendar || account.IsCalendarAccessGranted))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private async Task<bool> NavigateToMailEmptyStateIfNeededAsync()
|
||||
{
|
||||
var accounts = await _accountService.GetAccountsAsync().ConfigureAwait(false);
|
||||
if (!accounts.Any() || accounts.Any(account => account.IsMailAccessGranted))
|
||||
return false;
|
||||
|
||||
latestSelectedAccountMenuItem = null;
|
||||
await ExecuteUIThread(() => SelectedMenuItem = null);
|
||||
|
||||
NavigationService.Navigate(
|
||||
WinoPage.IdlePage,
|
||||
MailEmptyStateNavigationParameter,
|
||||
NavigationReferenceFrame.InnerShellFrame,
|
||||
NavigationTransitionType.None);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsAccountCurrentlyLoaded(Guid accountId)
|
||||
{
|
||||
return latestSelectedAccountMenuItem?.HoldingAccounts?.Any(a => a.Id == accountId) == true;
|
||||
@@ -1385,7 +1437,9 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
public async void Receive(AccountRemovedMessage message)
|
||||
{
|
||||
var remainingAccounts = await _accountService.GetAccountsAsync().ConfigureAwait(false);
|
||||
if (!remainingAccounts.Any())
|
||||
var remainingMailAccounts = remainingAccounts.Where(account => account.IsMailAccessGranted).ToList();
|
||||
|
||||
if (!remainingMailAccounts.Any())
|
||||
{
|
||||
latestSelectedAccountMenuItem = null;
|
||||
await ExecuteUIThread(() =>
|
||||
@@ -1394,6 +1448,12 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
MenuItems?.Clear();
|
||||
MenuItems?.Add(CreateMailMenuItem);
|
||||
});
|
||||
|
||||
if (remainingAccounts.Any())
|
||||
{
|
||||
await NavigateToMailEmptyStateIfNeededAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1413,22 +1473,34 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
|
||||
await RecreateMenuItemsAsync();
|
||||
|
||||
if (!createdAccount.IsMailAccessGranted)
|
||||
{
|
||||
await NavigateToMailEmptyStateIfNeededAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!MenuItems.TryGetAccountMenuItem(createdAccount.Id, out IAccountMenuItem createdMenuItem))
|
||||
{
|
||||
Log.Warning("Created account {AccountId} could not be found in menu items after refresh.", createdAccount.Id);
|
||||
|
||||
if (!createdAccount.IsMailAccessGranted)
|
||||
return;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await ChangeLoadedAccountAsync(createdMenuItem);
|
||||
|
||||
// Each created account should start a new synchronization automatically.
|
||||
var options = new MailSynchronizationOptions()
|
||||
if (createdAccount.IsMailAccessGranted)
|
||||
{
|
||||
AccountId = createdAccount.Id,
|
||||
Type = MailSynchronizationType.FullFolders,
|
||||
};
|
||||
// Each created account should start a new synchronization automatically.
|
||||
var options = new MailSynchronizationOptions()
|
||||
{
|
||||
AccountId = createdAccount.Id,
|
||||
Type = MailSynchronizationType.FullFolders,
|
||||
};
|
||||
|
||||
Messenger.Send(new NewMailSynchronizationRequested(options));
|
||||
Messenger.Send(new NewMailSynchronizationRequested(options));
|
||||
}
|
||||
|
||||
if (createdAccount.IsCalendarAccessGranted)
|
||||
{
|
||||
@@ -1455,6 +1527,13 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
||||
{
|
||||
var updatedAccount = message.Account;
|
||||
|
||||
if (!updatedAccount.IsMailAccessGranted || !MenuItems.TryGetAccountMenuItem(updatedAccount.Id, out _))
|
||||
{
|
||||
await RecreateMenuItemsAsync();
|
||||
await RestoreSelectedAccountAfterMenuRefreshAsync(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
if (MenuItems.TryGetAccountMenuItem(updatedAccount.Id, out IAccountMenuItem foundAccountMenuItem))
|
||||
|
||||
@@ -10,9 +10,7 @@ using Wino.Core.Domain.Entities.Mail;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Domain.Models.Synchronization;
|
||||
using Wino.Core.Requests.Category;
|
||||
using Wino.Core.Services;
|
||||
|
||||
@@ -53,11 +51,11 @@ public partial class MailCategoryManagementPageViewModel : MailBaseViewModel
|
||||
if (parameters is not Guid accountId)
|
||||
return;
|
||||
|
||||
Account = await _accountService.GetAccountAsync(accountId).ConfigureAwait(false);
|
||||
Account = await _accountService.GetAccountAsync(accountId);
|
||||
|
||||
if (Account != null)
|
||||
{
|
||||
await LoadCategoriesAsync().ConfigureAwait(false);
|
||||
await LoadCategoriesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,13 @@ using Wino.Messaging.Client.Navigation;
|
||||
|
||||
namespace Wino.Mail.ViewModels;
|
||||
|
||||
public enum ProviderSelectionWizardStep
|
||||
{
|
||||
Provider = 0,
|
||||
Identity = 1,
|
||||
Capabilities = 2
|
||||
}
|
||||
|
||||
public partial class ProviderSelectionPageViewModel : MailBaseViewModel
|
||||
{
|
||||
private readonly IAccountService _accountService;
|
||||
@@ -45,16 +52,50 @@ public partial class ProviderSelectionPageViewModel : MailBaseViewModel
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(IsInitialSynchronizationWarningVisible))]
|
||||
[NotifyPropertyChangedFor(nameof(IsMailSynchronizationRangeVisible))]
|
||||
public partial InitialSynchronizationRangeOption SelectedInitialSynchronizationRange { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string AccountName { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool CanProceed { get; set; }
|
||||
[NotifyPropertyChangedFor(nameof(IsMailSynchronizationRangeVisible))]
|
||||
public partial bool IsMailAccessEnabled { get; set; } = true;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsCalendarAccessEnabled { get; set; } = true;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(CurrentStepNumber))]
|
||||
[NotifyPropertyChangedFor(nameof(StepProgressValue))]
|
||||
[NotifyPropertyChangedFor(nameof(StepProgressText))]
|
||||
[NotifyPropertyChangedFor(nameof(IsProviderStepVisible))]
|
||||
[NotifyPropertyChangedFor(nameof(IsIdentityStepVisible))]
|
||||
[NotifyPropertyChangedFor(nameof(IsCapabilityStepVisible))]
|
||||
[NotifyPropertyChangedFor(nameof(CanGoBack))]
|
||||
[NotifyCanExecuteChangedFor(nameof(ContinueCommand))]
|
||||
[NotifyCanExecuteChangedFor(nameof(GoBackCommand))]
|
||||
public partial ProviderSelectionWizardStep CurrentStep { get; set; } = ProviderSelectionWizardStep.Provider;
|
||||
|
||||
public bool IsColorSelected => SelectedColor != null;
|
||||
public bool IsInitialSynchronizationWarningVisible => SelectedInitialSynchronizationRange?.IsEverything == true;
|
||||
public bool IsInitialSynchronizationWarningVisible => IsMailSynchronizationRangeVisible && SelectedInitialSynchronizationRange?.IsEverything == true;
|
||||
public bool IsMailSynchronizationRangeVisible => IsMailAccessEnabled;
|
||||
public int CurrentStepNumber => (int)CurrentStep + 1;
|
||||
public double StepProgressValue => CurrentStepNumber;
|
||||
public string StepProgressText => string.Format(Translator.ProviderSelection_StepProgress, CurrentStepNumber);
|
||||
public bool IsProviderStepVisible => CurrentStep == ProviderSelectionWizardStep.Provider;
|
||||
public bool IsIdentityStepVisible => CurrentStep == ProviderSelectionWizardStep.Identity;
|
||||
public bool IsCapabilityStepVisible => CurrentStep == ProviderSelectionWizardStep.Capabilities;
|
||||
public bool CanGoBack => CurrentStep != ProviderSelectionWizardStep.Provider;
|
||||
public string SelectedProviderName => SelectedProvider?.Name ?? string.Empty;
|
||||
public string SelectedProviderDescription => SelectedProvider?.Description ?? string.Empty;
|
||||
public string SelectedProviderImage => SelectedProvider?.ProviderImage ?? string.Empty;
|
||||
public string SelectedProviderCapabilityDescription => GetSelectedProviderCapabilityDescription();
|
||||
public bool IsCapabilitySelectionMissing => !IsMailAccessEnabled && !IsCalendarAccessEnabled;
|
||||
public bool IsCalendarOnlyServerHintVisible =>
|
||||
SelectedProvider?.Type == MailProviderType.IMAP4 &&
|
||||
!IsMailAccessEnabled &&
|
||||
IsCalendarAccessEnabled;
|
||||
|
||||
public ProviderSelectionPageViewModel(
|
||||
IAccountService accountService,
|
||||
@@ -101,48 +142,110 @@ public partial class ProviderSelectionPageViewModel : MailBaseViewModel
|
||||
p.Type == WizardContext.SelectedProvider.Type &&
|
||||
p.SpecialImapProvider == WizardContext.SelectedProvider.SpecialImapProvider);
|
||||
AccountName = WizardContext.AccountName;
|
||||
IsMailAccessEnabled = WizardContext.IsMailAccessEnabled;
|
||||
IsCalendarAccessEnabled = WizardContext.IsCalendarAccessEnabled;
|
||||
|
||||
if (WizardContext.AccountColorHex != null)
|
||||
SelectedColor = AvailableColors.FirstOrDefault(c => c.Hex == WizardContext.AccountColorHex);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsMailAccessEnabled = true;
|
||||
IsCalendarAccessEnabled = true;
|
||||
}
|
||||
|
||||
Validate();
|
||||
CurrentStep = mode == NavigationMode.Back && SelectedProvider != null
|
||||
? ProviderSelectionWizardStep.Capabilities
|
||||
: ProviderSelectionWizardStep.Provider;
|
||||
}
|
||||
|
||||
partial void OnSelectedProviderChanged(IProviderDetail value)
|
||||
{
|
||||
Validate();
|
||||
OnPropertyChanged(nameof(SelectedProviderName));
|
||||
OnPropertyChanged(nameof(SelectedProviderDescription));
|
||||
OnPropertyChanged(nameof(SelectedProviderImage));
|
||||
OnPropertyChanged(nameof(SelectedProviderCapabilityDescription));
|
||||
OnPropertyChanged(nameof(IsCapabilitySelectionMissing));
|
||||
OnPropertyChanged(nameof(IsCalendarOnlyServerHintVisible));
|
||||
ContinueCommand.NotifyCanExecuteChanged();
|
||||
}
|
||||
|
||||
partial void OnAccountNameChanged(string value) => Validate();
|
||||
partial void OnAccountNameChanged(string value) => ContinueCommand.NotifyCanExecuteChanged();
|
||||
|
||||
partial void OnIsMailAccessEnabledChanged(bool value)
|
||||
{
|
||||
OnPropertyChanged(nameof(IsCapabilitySelectionMissing));
|
||||
OnPropertyChanged(nameof(IsCalendarOnlyServerHintVisible));
|
||||
ContinueCommand.NotifyCanExecuteChanged();
|
||||
}
|
||||
|
||||
partial void OnIsCalendarAccessEnabledChanged(bool value)
|
||||
{
|
||||
OnPropertyChanged(nameof(IsCapabilitySelectionMissing));
|
||||
OnPropertyChanged(nameof(IsCalendarOnlyServerHintVisible));
|
||||
ContinueCommand.NotifyCanExecuteChanged();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ClearColor() => SelectedColor = null;
|
||||
|
||||
private void Validate()
|
||||
private bool CanContinue()
|
||||
{
|
||||
CanProceed = SelectedProvider != null && !string.IsNullOrWhiteSpace(AccountName);
|
||||
return CurrentStep switch
|
||||
{
|
||||
ProviderSelectionWizardStep.Provider => SelectedProvider != null,
|
||||
ProviderSelectionWizardStep.Identity => !string.IsNullOrWhiteSpace(AccountName),
|
||||
ProviderSelectionWizardStep.Capabilities => IsMailAccessEnabled || IsCalendarAccessEnabled,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task ProceedAsync()
|
||||
[RelayCommand(CanExecute = nameof(CanGoBack))]
|
||||
private void GoBack()
|
||||
{
|
||||
if (!CanProceed) return;
|
||||
|
||||
if (await _accountService.AccountNameExistsAsync(AccountName))
|
||||
{
|
||||
await _dialogService.ShowMessageAsync(
|
||||
Translator.DialogMessage_AccountNameExistsMessage,
|
||||
Translator.DialogMessage_AccountExistsTitle,
|
||||
WinoCustomMessageDialogIcon.Warning);
|
||||
if (!CanGoBack)
|
||||
return;
|
||||
|
||||
CurrentStep--;
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanContinue))]
|
||||
private async Task ContinueAsync()
|
||||
{
|
||||
switch (CurrentStep)
|
||||
{
|
||||
case ProviderSelectionWizardStep.Provider:
|
||||
CurrentStep = ProviderSelectionWizardStep.Identity;
|
||||
return;
|
||||
case ProviderSelectionWizardStep.Identity:
|
||||
if (await _accountService.AccountNameExistsAsync(AccountName?.Trim()))
|
||||
{
|
||||
await _dialogService.ShowMessageAsync(
|
||||
Translator.DialogMessage_AccountNameExistsMessage,
|
||||
Translator.DialogMessage_AccountExistsTitle,
|
||||
WinoCustomMessageDialogIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentStep = ProviderSelectionWizardStep.Capabilities;
|
||||
return;
|
||||
case ProviderSelectionWizardStep.Capabilities:
|
||||
await CompleteWizardAsync();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CompleteWizardAsync()
|
||||
{
|
||||
if (!CanContinue())
|
||||
return;
|
||||
}
|
||||
|
||||
// Persist to wizard context
|
||||
WizardContext.SelectedProvider = SelectedProvider;
|
||||
WizardContext.AccountName = AccountName?.Trim();
|
||||
WizardContext.AccountColorHex = SelectedColor?.Hex ?? string.Empty;
|
||||
WizardContext.SelectedInitialSynchronizationRange = SelectedInitialSynchronizationRange?.Range ?? InitialSynchronizationRange.SixMonths;
|
||||
WizardContext.IsMailAccessEnabled = IsMailAccessEnabled;
|
||||
WizardContext.IsCalendarAccessEnabled = IsCalendarAccessEnabled;
|
||||
|
||||
if (WizardContext.IsGenericImap)
|
||||
{
|
||||
@@ -172,4 +275,23 @@ public partial class ProviderSelectionPageViewModel : MailBaseViewModel
|
||||
WinoPage.AccountSetupProgressPage));
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnSelectedProviderChanging(IProviderDetail value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private string GetSelectedProviderCapabilityDescription()
|
||||
{
|
||||
if (SelectedProvider == null)
|
||||
return string.Empty;
|
||||
|
||||
if (SelectedProvider.Type is MailProviderType.Outlook or MailProviderType.Gmail)
|
||||
return Translator.ProviderSelection_CapabilityProviderDescription_OAuth;
|
||||
|
||||
if (SelectedProvider.SpecialImapProvider is SpecialImapProvider.iCloud or SpecialImapProvider.Yahoo)
|
||||
return Translator.ProviderSelection_CapabilityProviderDescription_SpecialImap;
|
||||
|
||||
return Translator.ProviderSelection_CapabilityProviderDescription_CustomServer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,15 @@ public partial class SpecialImapCredentialsPageViewModel : MailBaseViewModel
|
||||
public partial string AppSpecificPassword { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(RequiresAppSpecificPassword))]
|
||||
public partial int SelectedCalendarModeIndex { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool CanProceed { get; set; }
|
||||
|
||||
public bool IsCalendarModeSelectionVisible => WizardContext.IsCalendarAccessEnabled;
|
||||
public bool RequiresAppSpecificPassword => WizardContext.IsMailAccessEnabled || SelectedCalendarModeIndex == 1;
|
||||
|
||||
public string AppPasswordHelpUrl
|
||||
{
|
||||
get
|
||||
@@ -86,8 +90,15 @@ public partial class SpecialImapCredentialsPageViewModel : MailBaseViewModel
|
||||
_ => 0
|
||||
};
|
||||
|
||||
if (!WizardContext.IsCalendarAccessEnabled)
|
||||
{
|
||||
SelectedCalendarModeIndex = 0;
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(AppPasswordHelpUrl));
|
||||
OnPropertyChanged(nameof(CalendarModeCalDavDescription));
|
||||
OnPropertyChanged(nameof(IsCalendarModeSelectionVisible));
|
||||
OnPropertyChanged(nameof(RequiresAppSpecificPassword));
|
||||
|
||||
Validate();
|
||||
}
|
||||
@@ -95,13 +106,18 @@ public partial class SpecialImapCredentialsPageViewModel : MailBaseViewModel
|
||||
partial void OnDisplayNameChanged(string value) => Validate();
|
||||
partial void OnEmailAddressChanged(string value) => Validate();
|
||||
partial void OnAppSpecificPasswordChanged(string value) => Validate();
|
||||
partial void OnSelectedCalendarModeIndexChanged(int value)
|
||||
{
|
||||
OnPropertyChanged(nameof(RequiresAppSpecificPassword));
|
||||
Validate();
|
||||
}
|
||||
|
||||
private void Validate()
|
||||
{
|
||||
CanProceed = !string.IsNullOrWhiteSpace(DisplayName)
|
||||
&& !string.IsNullOrWhiteSpace(EmailAddress)
|
||||
&& MailAccountAddressValidator.IsValid(EmailAddress)
|
||||
&& !string.IsNullOrWhiteSpace(AppSpecificPassword);
|
||||
&& (!RequiresAppSpecificPassword || !string.IsNullOrWhiteSpace(AppSpecificPassword));
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
@@ -121,12 +137,14 @@ public partial class SpecialImapCredentialsPageViewModel : MailBaseViewModel
|
||||
WizardContext.DisplayName = DisplayName?.Trim();
|
||||
WizardContext.EmailAddress = EmailAddress?.Trim();
|
||||
WizardContext.AppSpecificPassword = AppSpecificPassword?.Trim();
|
||||
WizardContext.CalendarSupportMode = SelectedCalendarModeIndex switch
|
||||
{
|
||||
1 => ImapCalendarSupportMode.CalDav,
|
||||
2 => ImapCalendarSupportMode.LocalOnly,
|
||||
_ => ImapCalendarSupportMode.Disabled
|
||||
};
|
||||
WizardContext.CalendarSupportMode = WizardContext.IsCalendarAccessEnabled
|
||||
? SelectedCalendarModeIndex switch
|
||||
{
|
||||
1 => ImapCalendarSupportMode.CalDav,
|
||||
2 => ImapCalendarSupportMode.LocalOnly,
|
||||
_ => ImapCalendarSupportMode.Disabled
|
||||
}
|
||||
: ImapCalendarSupportMode.Disabled;
|
||||
|
||||
Messenger.Send(new BreadcrumbNavigationRequested(
|
||||
Translator.WelcomeWizard_Step3Title,
|
||||
|
||||
Reference in New Issue
Block a user