diff --git a/.codex/environments/environment.toml b/.codex/environments/environment.toml new file mode 100644 index 00000000..ff363268 --- /dev/null +++ b/.codex/environments/environment.toml @@ -0,0 +1,6 @@ +# THIS IS AUTOGENERATED. DO NOT EDIT MANUALLY +version = 1 +name = "Wino-Mail" + +[setup] +script = "" diff --git a/Wino.Core.Domain/Enums/WinoPage.cs b/Wino.Core.Domain/Enums/WinoPage.cs index f7525f39..ddef5f89 100644 --- a/Wino.Core.Domain/Enums/WinoPage.cs +++ b/Wino.Core.Domain/Enums/WinoPage.cs @@ -26,7 +26,6 @@ public enum WinoPage AppPreferencesPage, SettingOptionsPage, AliasManagementPage, - EditAccountDetailsPage, ImapCalDavSettingsPage, KeyboardShortcutsPage, CalendarPage, diff --git a/Wino.Core.Domain/Translations/en_US/resources.json b/Wino.Core.Domain/Translations/en_US/resources.json index 450d873a..ea3c6d13 100644 --- a/Wino.Core.Domain/Translations/en_US/resources.json +++ b/Wino.Core.Domain/Translations/en_US/resources.json @@ -127,6 +127,7 @@ "CalendarEventDetails_Attachments": "Attachments", "CalendarEventCompose_AddAttachment": "Add attachment", "CalendarEventCompose_AllDay": "All Day", + "CalendarEventCompose_AttachmentsNotSupportedForCalDav": "Attachments are not supported for CalDAV calendars.", "CalendarEventCompose_EndDate": "End date", "CalendarEventCompose_EndTime": "End time", "CalendarEventCompose_Every": "every", @@ -251,6 +252,8 @@ "DialogMessage_CreateLinkedAccountTitle": "Account Link Name", "DialogMessage_DeleteAccountConfirmationMessage": "Delete {0}?", "DialogMessage_DeleteAccountConfirmationTitle": "All data associated with this account will be deleted from disk permanently.", + "DialogMessage_DeleteEmailTemplateConfirmationMessage": "Delete template \"{0}\"?", + "DialogMessage_DeleteEmailTemplateConfirmationTitle": "Delete Email Template", "DialogMessage_DeleteRecurringSeriesMessage": "This will delete all events in the series. Do you want to continue?", "DialogMessage_DeleteRecurringSeriesTitle": "Delete Recurring Series", "DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?", @@ -361,19 +364,29 @@ "KeyboardShortcuts_FailedToReset": "Failed to reset keyboard shortcuts.", "KeyboardShortcuts_FailedToUpdate": "Failed to update keyboard shortcuts", "KeyboardShortcuts_MailoperationAction": "Action", + "KeyboardShortcuts_Action": "Action", "KeyboardShortcuts_FailedToLoad": "Failed to load keyboard shortcuts.", "KeyboardShortcuts_EnterKeyForShortcut": "Please enter a key for the shortcut.", "KeyboardShortcuts_SelectOperationForShortcut": "Please an action to perform for the shortcut.", + "KeyboardShortcuts_EnterKey": "Please enter a key for the shortcut.", + "KeyboardShortcuts_SelectOperation": "Please select an action for the shortcut.", "KeyboardShortcuts_ShortcutInUse": "This shortcut is already in use by another s hortcut.", "KeyboardShortcuts_FailedToSave": "Failed to save the shortcut.", "KeyboardShortcuts_FailedToDelete": "Failed to delete the shortcut.", "KeyboardShortcuts_PageDescription": "Set up keyboard shortcuts for quick mail operations. Press keys while focused on the key input field to capture shortcuts.", "KeyboardShortcuts_Add": "Add shortcut", + "KeyboardShortcuts_EditTitle": "Edit Keyboard Shortcut", "KeyboardShortcuts_ResetToDefaults": "Reset to Defaults", "KeyboardShortcuts_PressKeysHere": "Press keys here...", "KeyboardShortcuts_KeyCombination": "Key Combination", "KeyboardShortcuts_FocusArea": "Focus the field above and press the desired key combination", "KeyboardShortcuts_Modifiers": "Modifier Keys", + "KeyboardShortcuts_Mode": "App Mode", + "KeyboardShortcuts_ModeMail": "Mail", + "KeyboardShortcuts_ModeCalendar": "Calendar", + "KeyboardShortcuts_ActionToggleReadUnread": "Toggle read/unread", + "KeyboardShortcuts_ActionToggleFlag": "Toggle flag", + "KeyboardShortcuts_ActionToggleArchive": "Toggle archive/unarchive", "ImageRenderingDisabled": "Image rendering is disabled for this message.", "ImapAdvancedSetupDialog_AuthenticationMethod": "Authentication method", "ImapAdvancedSetupDialog_ConnectionSecurity": "Connection security", @@ -556,6 +569,7 @@ "InfoBarMessage_SynchronizationDisabledFolder": "This folder is disabled for synchronization.", "InfoBarTitle_SynchronizationDisabledFolder": "Disabled Folder", "Justify": "Justify", + "MenuUpdateAvailable": "Update Available", "Left": "Left", "Link": "Link", "LinkedAccountsCreatePolicyMessage": "you must have at least 2 accounts to create link\nlink will be removed on save", @@ -621,6 +635,8 @@ "Notifications_MultipleNotificationsTitle": "New Mail", "Notifications_WinoUpdatedMessage": "Checkout new version {0}", "Notifications_WinoUpdatedTitle": "Wino Mail has been updated.", + "Notifications_StoreUpdateAvailableTitle": "Update available", + "Notifications_StoreUpdateAvailableMessage": "A newer version of Wino Mail is ready to install from Microsoft Store.", "OnlineSearchFailed_Message": "Failed to perform search\n{0}\n\nListing offline mails.", "OnlineSearchTry_Line1": "Can't find what you are looking for?", "OnlineSearchTry_Line2": "Try online search.", @@ -699,6 +715,8 @@ "SettingsAppPreferences_StartupBehavior_FatalError": "Fatal error occurred while changing the startup mode for Wino Mail.", "SettingsAppPreferences_StartupBehavior_Title": "Start minimized on Windows startup", "SettingsAppPreferences_Title": "App Preferences", + "SettingsAppPreferences_StoreUpdateNotifications_Title": "Store update notifications", + "SettingsAppPreferences_StoreUpdateNotifications_Description": "Show notifications and footer actions when a Microsoft Store update is available.", "SettingsAutoSelectNextItem_Description": "Select the next item after you delete or move a mail.", "SettingsAutoSelectNextItem_Title": "Auto select next item", "SettingsAvailableThemes_Description": "Select a theme from Wino's own collection for your taste or apply your own themes.", @@ -779,6 +797,8 @@ "SettingsManageAliases_Title": "Aliases", "SettingsEditAccountDetails_Title": "Edit Account Details", "SettingsEditAccountDetails_Description": "Change account name, sender name and assign a new color if you like.", + "EditAccountDetailsPage_SaveSuccess_Title": "Changes Saved", + "EditAccountDetailsPage_SaveSuccess_Message": "Your account details have been updated successfully.", "SettingsManageLink_Description": "Move items to add new link or remove existing link.", "SettingsManageLink_Title": "Manage Link", "SettingsMarkAsRead_Description": "Change what should happen to the selected item.", @@ -831,6 +851,19 @@ "SettingsShowPreviewText_Title": "Show Preview Text", "SettingsShowSenderPictures_Description": "Hide/show the thumbnail sender pictures.", "SettingsShowSenderPictures_Title": "Show Sender Avatars", + "SettingsEmailTemplates_Title": "Email Templates", + "SettingsEmailTemplates_Description": "Manage e-mail templates", + "SettingsEmailTemplates_CreatePageTitle": "New template", + "SettingsEmailTemplates_EditPageTitle": "Edit template", + "SettingsEmailTemplates_NewTemplateTitle": "New template", + "SettingsEmailTemplates_NewTemplateDescription": "Create a new e-mail template", + "SettingsEmailTemplates_NameTitle": "Name", + "SettingsEmailTemplates_NamePlaceholder": "Template name", + "SettingsEmailTemplates_DescriptionTitle": "Description", + "SettingsEmailTemplates_DescriptionPlaceholder": "Optional description", + "SettingsEmailTemplates_ContentTitle": "Template content", + "SettingsEmailTemplates_ContentDescription": "Edit the HTML content for this template.", + "SettingsEmailTemplates_NameRequired": "Template name is required.", "SettingsEnableGravatarAvatars_Title": "Gravatar", "SettingsEnableGravatarAvatars_Description": "Use gravatar (if available) as sender picture", "SettingsEnableFavicons_Title": "Domain icons (Favicons)", @@ -990,6 +1023,7 @@ "Composer_CertificateExpires": "Expires on: ", "Composer_SmimeSignature": "S/MIME Signature", "Composer_SmimeEncryption": "S/MIME Encryption", + "Composer_EmailTemplatesPlaceholder": "E-mail templates", "SettingsAppPreferences_EmailSyncInterval_Title": "Email sync interval", "SettingsAppPreferences_EmailSyncInterval_Description": "Automatic email synchronization interval (minutes). This setting will be applied only after restarting Wino Mail.", "ContactsPage_Title": "Contacts", diff --git a/Wino.Mail.ViewModels/AccountDetailsPageViewModel.cs b/Wino.Mail.ViewModels/AccountDetailsPageViewModel.cs index 7f24642e..e9eb768a 100644 --- a/Wino.Mail.ViewModels/AccountDetailsPageViewModel.cs +++ b/Wino.Mail.ViewModels/AccountDetailsPageViewModel.cs @@ -12,9 +12,11 @@ using Wino.Core.Domain; using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Enums; 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.Services; +using Wino.Core.ViewModels.Data; using Wino.Mail.ViewModels.Data; using Wino.Messaging.Client.Calendar; using Wino.Messaging.Client.Navigation; @@ -28,9 +30,12 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel private readonly IFolderService _folderService; private readonly ICalendarService _calendarService; private readonly IStatePersistanceService _statePersistanceService; + private readonly INewThemeService _themeService; + private readonly IImapTestService _imapTestService; private bool isLoaded = false; - public MailAccount Account { get; set; } + [ObservableProperty] + public partial MailAccount Account { get; set; } public ObservableCollection CurrentFolders { get; set; } = []; public ObservableCollection AccountCalendars { get; set; } = []; public ObservableCollection AccountCalendarSettingsItems { get; } = []; @@ -40,7 +45,35 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel public partial AccountCalendar SelectedPrimaryCalendar { get; set; } [ObservableProperty] - public partial int SelectedTabIndex { get; set; } = 1; // Default to Mail tab + public partial int SelectedTabIndex { get; set; } = 0; // Default to Mail tab + + [ObservableProperty] + public partial string AccountName { get; set; } + + [ObservableProperty] + public partial string SenderName { get; set; } + + [ObservableProperty] + public partial AppColorViewModel SelectedColor { get; set; } + + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(IsImapServer))] + public partial CustomServerInformation ServerInformation { get; set; } + + [ObservableProperty] + public partial List AvailableColors { get; set; } + + [ObservableProperty] + public partial int SelectedIncomingServerConnectionSecurityIndex { get; set; } + + [ObservableProperty] + public partial int SelectedIncomingServerAuthenticationMethodIndex { get; set; } + + [ObservableProperty] + public partial int SelectedOutgoingServerConnectionSecurityIndex { get; set; } + + [ObservableProperty] + public partial int SelectedOutgoingServerAuthenticationMethodIndex { get; set; } // Mail-related properties [ObservableProperty] @@ -62,19 +95,50 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel private bool isTaskbarBadgeEnabled; public bool IsFocusedInboxSupportedForAccount => Account != null && Account.Preferences.IsFocusedInboxEnabled != null; + public bool IsImapServer => ServerInformation != null; + public string ProviderIconPath => Account?.SpecialImapProvider != SpecialImapProvider.None + ? $"ms-appx:///Assets/Providers/{Account.SpecialImapProvider}.png" + : $"ms-appx:///Assets/Providers/{Account?.ProviderType}.png"; + public string Address => Account?.Address ?? string.Empty; + + public List AvailableAuthenticationMethods { get; } = + [ + new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.Auto, Translator.ImapAuthenticationMethod_Auto), + new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.None, Translator.ImapAuthenticationMethod_None), + new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.NormalPassword, Translator.ImapAuthenticationMethod_Plain), + new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.EncryptedPassword, Translator.ImapAuthenticationMethod_EncryptedPassword), + new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.Ntlm, Translator.ImapAuthenticationMethod_Ntlm), + new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.CramMd5, Translator.ImapAuthenticationMethod_CramMD5), + new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.DigestMd5, Translator.ImapAuthenticationMethod_DigestMD5) + ]; + + public List AvailableConnectionSecurities { get; set; } = + [ + new ImapConnectionSecurityModel(Core.Domain.Enums.ImapConnectionSecurity.Auto, Translator.ImapConnectionSecurity_Auto), + new ImapConnectionSecurityModel(Core.Domain.Enums.ImapConnectionSecurity.SslTls, Translator.ImapConnectionSecurity_SslTls), + new ImapConnectionSecurityModel(Core.Domain.Enums.ImapConnectionSecurity.StartTls, Translator.ImapConnectionSecurity_StartTls), + new ImapConnectionSecurityModel(Core.Domain.Enums.ImapConnectionSecurity.None, Translator.ImapConnectionSecurity_None) + ]; public AccountDetailsPageViewModel(IMailDialogService dialogService, IAccountService accountService, IFolderService folderService, ICalendarService calendarService, - IStatePersistanceService statePersistanceService) + IStatePersistanceService statePersistanceService, + INewThemeService themeService, + IImapTestService imapTestService) { _dialogService = dialogService; _accountService = accountService; _folderService = folderService; _calendarService = calendarService; _statePersistanceService = statePersistanceService; + _themeService = themeService; + _imapTestService = imapTestService; + + var colorHexList = _themeService.GetAvailableAccountColors(); + AvailableColors = colorHexList.Select(a => new AppColorViewModel(a)).ToList(); ShowAsOptions.Add(new AccountCalendarShowAsOption(CalendarItemShowAs.Free, Translator.CalendarShowAs_Free)); ShowAsOptions.Add(new AccountCalendarShowAsOption(CalendarItemShowAs.Tentative, Translator.CalendarShowAs_Tentative)); @@ -95,41 +159,28 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel private void EditAliases() => Messenger.Send(new BreadcrumbNavigationRequested(Translator.SettingsManageAliases_Title, WinoPage.AliasManagementPage, Account.Id)); - public Task FolderSyncToggledAsync(IMailItemFolder folderStructure, bool isEnabled) - => _folderService.ChangeFolderSynchronizationStateAsync(folderStructure.Id, isEnabled); - - public Task FolderShowUnreadToggled(IMailItemFolder folderStructure, bool isEnabled) - => _folderService.ChangeFolderShowUnreadCountStateAsync(folderStructure.Id, isEnabled); - [RelayCommand] - private void EditAccountDetails() + private async Task SaveChangesAsync() { - if (Account?.ProviderType == MailProviderType.IMAP4) - { - var context = ImapCalDavSettingsNavigationContext.CreateForEditMode(Account.Id); - Messenger.Send(new BreadcrumbNavigationRequested(Translator.ImapCalDavSettingsPage_TitleEdit, WinoPage.ImapCalDavSettingsPage, context)); - return; - } + await UpdateAccountAsync(); - Messenger.Send(new BreadcrumbNavigationRequested(Translator.SettingsEditAccountDetails_Title, WinoPage.EditAccountDetailsPage, Account)); + _dialogService.InfoBarMessage(Translator.EditAccountDetailsPage_SaveSuccess_Title, Translator.EditAccountDetailsPage_SaveSuccess_Message, InfoBarMessageType.Success); } [RelayCommand] - private async Task DeleteAccount() + private async Task DeleteAccountAsync() { if (Account == null) return; var confirmation = await _dialogService.ShowConfirmationDialogAsync(Translator.DialogMessage_DeleteAccountConfirmationTitle, - string.Format(Translator.DialogMessage_DeleteAccountConfirmationMessage, Account.Name), - Translator.Buttons_Delete); + string.Format(Translator.DialogMessage_DeleteAccountConfirmationMessage, Account.Name), + Translator.Buttons_Delete); if (!confirmation) return; - await SynchronizationManager.Instance.DestroySynchronizerAsync(Account.Id); - await _accountService.DeleteAccountAsync(Account); _dialogService.InfoBarMessage(Translator.Info_AccountDeletedTitle, string.Format(Translator.Info_AccountDeletedMessage, Account.Name), InfoBarMessageType.Success); @@ -137,6 +188,44 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel Messenger.Send(new BackBreadcrumNavigationRequested()); } + [RelayCommand] + private async Task ValidateImapSettingsAsync() + { + try + { + await _imapTestService.TestImapConnectionAsync(ServerInformation, true); + _dialogService.InfoBarMessage(Translator.IMAPSetupDialog_ValidationSuccess_Title, Translator.IMAPSetupDialog_ValidationSuccess_Message, InfoBarMessageType.Success); + } + catch (Exception ex) + { + _dialogService.InfoBarMessage(Translator.IMAPSetupDialog_ValidationFailed_Title, ex.Message, InfoBarMessageType.Error); + } + } + + [RelayCommand] + private async Task UpdateCustomServerInformationAsync() + { + if (ServerInformation != null) + { + ServerInformation.IncomingAuthenticationMethod = AvailableAuthenticationMethods[SelectedIncomingServerAuthenticationMethodIndex].ImapAuthenticationMethod; + ServerInformation.IncomingServerSocketOption = AvailableConnectionSecurities[SelectedIncomingServerConnectionSecurityIndex].ImapConnectionSecurity; + + ServerInformation.OutgoingAuthenticationMethod = AvailableAuthenticationMethods[SelectedOutgoingServerAuthenticationMethodIndex].ImapAuthenticationMethod; + ServerInformation.OutgoingServerSocketOption = AvailableConnectionSecurities[SelectedOutgoingServerConnectionSecurityIndex].ImapConnectionSecurity; + + Account.ServerInformation = ServerInformation; + } + + await _accountService.UpdateAccountCustomServerInformationAsync(Account.ServerInformation); + + _dialogService.InfoBarMessage(Translator.IMAPSetupDialog_SaveImapSuccess_Title, Translator.IMAPSetupDialog_SaveImapSuccess_Message, InfoBarMessageType.Success); + } + + public Task FolderSyncToggledAsync(IMailItemFolder folderStructure, bool isEnabled) + => _folderService.ChangeFolderSynchronizationStateAsync(folderStructure.Id, isEnabled); + + public Task FolderShowUnreadToggled(IMailItemFolder folderStructure, bool isEnabled) + => _folderService.ChangeFolderShowUnreadCountStateAsync(folderStructure.Id, isEnabled); public override async void OnNavigatedTo(NavigationMode mode, object parameters) { @@ -145,6 +234,9 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel if (parameters is Guid accountId) { Account = await _accountService.GetAccountAsync(accountId); + AccountName = Account.Name; + SenderName = Account.SenderName; + ServerInformation = Account.ServerInformation; IsFocusedInboxEnabled = Account.Preferences.IsFocusedInboxEnabled.GetValueOrDefault(); AreNotificationsEnabled = Account.Preferences.IsNotificationsEnabled; @@ -154,9 +246,24 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel IsAppendMessageSettinEnabled = Account.Preferences.ShouldAppendMessagesToSentFolder; IsTaskbarBadgeEnabled = Account.Preferences.IsTaskbarBadgeEnabled; - OnPropertyChanged(nameof(IsFocusedInboxSupportedForAccount)); + if (!string.IsNullOrEmpty(Account.AccountColorHex)) + { + SelectedColor = AvailableColors.FirstOrDefault(a => a.Hex == Account.AccountColorHex); + } + else + { + SelectedColor = null; + } - SelectedTabIndex = _statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar ? 2 : 1; + if (ServerInformation != null) + { + SelectedIncomingServerAuthenticationMethodIndex = AvailableAuthenticationMethods.FindIndex(a => a.ImapAuthenticationMethod == ServerInformation.IncomingAuthenticationMethod); + SelectedIncomingServerConnectionSecurityIndex = AvailableConnectionSecurities.FindIndex(a => a.ImapConnectionSecurity == ServerInformation.IncomingServerSocketOption); + SelectedOutgoingServerAuthenticationMethodIndex = AvailableAuthenticationMethods.FindIndex(a => a.ImapAuthenticationMethod == ServerInformation.OutgoingAuthenticationMethod); + SelectedOutgoingServerConnectionSecurityIndex = AvailableConnectionSecurities.FindIndex(a => a.ImapConnectionSecurity == ServerInformation.OutgoingServerSocketOption); + } + + SelectedTabIndex = _statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar ? 1 : 0; var folderStructures = (await _folderService.GetFolderStructureForAccountAsync(Account.Id, true)).Folders; @@ -172,6 +279,15 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel } } + private Task UpdateAccountAsync() + { + Account.Name = AccountName; + Account.SenderName = SenderName; + Account.AccountColorHex = SelectedColor?.Hex ?? string.Empty; + + return _accountService.UpdateAccountAsync(Account); + } + private async Task LoadAccountCalendarsAsync() { var calendars = await _calendarService.GetAccountCalendarsAsync(Account.Id); @@ -212,6 +328,25 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel await _calendarService.UpdateAccountCalendarAsync(calendar); } + [RelayCommand] + private void ResetColor() + => SelectedColor = null; + + partial void OnSelectedColorChanged(AppColorViewModel oldValue, AppColorViewModel newValue) + { + if (Account != null) + { + _ = UpdateAccountAsync(); + } + } + + partial void OnAccountChanged(MailAccount value) + { + OnPropertyChanged(nameof(IsFocusedInboxSupportedForAccount)); + OnPropertyChanged(nameof(ProviderIconPath)); + OnPropertyChanged(nameof(Address)); + } + protected override async void OnPropertyChanged(PropertyChangedEventArgs e) { base.OnPropertyChanged(e); diff --git a/Wino.Mail.ViewModels/EditAccountDetailsPageViewModel.cs b/Wino.Mail.ViewModels/EditAccountDetailsPageViewModel.cs deleted file mode 100644 index 1cefc7c1..00000000 --- a/Wino.Mail.ViewModels/EditAccountDetailsPageViewModel.cs +++ /dev/null @@ -1,178 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.Mvvm.Messaging; -using Wino.Core.Domain; -using Wino.Core.Domain.Entities.Shared; -using Wino.Core.Domain.Interfaces; -using Wino.Core.Domain.Models.Accounts; -using Wino.Core.Domain.Models.Navigation; -using Wino.Core.ViewModels.Data; -using Wino.Messaging.Client.Navigation; - -namespace Wino.Mail.ViewModels; - -public partial class EditAccountDetailsPageViewModel : MailBaseViewModel -{ - private readonly IAccountService _accountService; - private readonly INewThemeService _themeService; - private readonly IImapTestService _imapTestService; - private readonly IMailDialogService _mailDialogService; - - [ObservableProperty] - public partial MailAccount Account { get; set; } - - [ObservableProperty] - public partial string AccountName { get; set; } - - [ObservableProperty] - public partial string SenderName { get; set; } - - [ObservableProperty] - public partial AppColorViewModel SelectedColor { get; set; } - - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(IsImapServer))] - public partial CustomServerInformation ServerInformation { get; set; } - - [ObservableProperty] - public partial List AvailableColors { get; set; } - - - [ObservableProperty] - public partial int SelectedIncomingServerConnectionSecurityIndex { get; set; } - - [ObservableProperty] - public partial int SelectedIncomingServerAuthenticationMethodIndex { get; set; } - - [ObservableProperty] - public partial int SelectedOutgoingServerConnectionSecurityIndex { get; set; } - - [ObservableProperty] - public partial int SelectedOutgoingServerAuthenticationMethodIndex { get; set; } - - public List AvailableAuthenticationMethods { get; } = - [ - new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.Auto, Translator.ImapAuthenticationMethod_Auto), - new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.None, Translator.ImapAuthenticationMethod_None), - new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.NormalPassword, Translator.ImapAuthenticationMethod_Plain), - new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.EncryptedPassword, Translator.ImapAuthenticationMethod_EncryptedPassword), - new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.Ntlm, Translator.ImapAuthenticationMethod_Ntlm), - new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.CramMd5, Translator.ImapAuthenticationMethod_CramMD5), - new ImapAuthenticationMethodModel(Core.Domain.Enums.ImapAuthenticationMethod.DigestMd5, Translator.ImapAuthenticationMethod_DigestMD5) - ]; - - public List AvailableConnectionSecurities { get; set; } = - [ - new ImapConnectionSecurityModel(Core.Domain.Enums.ImapConnectionSecurity.Auto, Translator.ImapConnectionSecurity_Auto), - new ImapConnectionSecurityModel(Core.Domain.Enums.ImapConnectionSecurity.SslTls, Translator.ImapConnectionSecurity_SslTls), - new ImapConnectionSecurityModel(Core.Domain.Enums.ImapConnectionSecurity.StartTls, Translator.ImapConnectionSecurity_StartTls), - new ImapConnectionSecurityModel(Core.Domain.Enums.ImapConnectionSecurity.None, Translator.ImapConnectionSecurity_None) - ]; - - public bool IsImapServer => ServerInformation != null; - - public EditAccountDetailsPageViewModel(IAccountService accountService, - INewThemeService themeService, - IImapTestService imapTestService, - IMailDialogService mailDialogService) - { - _accountService = accountService; - _themeService = themeService; - _imapTestService = imapTestService; - _mailDialogService = mailDialogService; - - var colorHexList = _themeService.GetAvailableAccountColors(); - - AvailableColors = colorHexList.Select(a => new AppColorViewModel(a)).ToList(); - } - - [RelayCommand] - private async Task SaveChangesAsync() - { - await UpdateAccountAsync(); - - Messenger.Send(new BackBreadcrumNavigationRequested()); - } - - [RelayCommand] - private async Task ValidateImapSettingsAsync() - { - try - { - await _imapTestService.TestImapConnectionAsync(ServerInformation, true); - _mailDialogService.InfoBarMessage(Translator.IMAPSetupDialog_ValidationSuccess_Title, Translator.IMAPSetupDialog_ValidationSuccess_Message, Core.Domain.Enums.InfoBarMessageType.Success); - } - catch (Exception ex) - { - _mailDialogService.InfoBarMessage(Translator.IMAPSetupDialog_ValidationFailed_Title, ex.Message, Core.Domain.Enums.InfoBarMessageType.Error); ; - } - } - - [RelayCommand] - private async Task UpdateCustomServerInformationAsync() - { - if (ServerInformation != null) - { - ServerInformation.IncomingAuthenticationMethod = AvailableAuthenticationMethods[SelectedIncomingServerAuthenticationMethodIndex].ImapAuthenticationMethod; - ServerInformation.IncomingServerSocketOption = AvailableConnectionSecurities[SelectedIncomingServerConnectionSecurityIndex].ImapConnectionSecurity; - - ServerInformation.OutgoingAuthenticationMethod = AvailableAuthenticationMethods[SelectedOutgoingServerAuthenticationMethodIndex].ImapAuthenticationMethod; - ServerInformation.OutgoingServerSocketOption = AvailableConnectionSecurities[SelectedOutgoingServerConnectionSecurityIndex].ImapConnectionSecurity; - - Account.ServerInformation = ServerInformation; - } - - await _accountService.UpdateAccountCustomServerInformationAsync(Account.ServerInformation); - - _mailDialogService.InfoBarMessage(Translator.IMAPSetupDialog_SaveImapSuccess_Title, Translator.IMAPSetupDialog_SaveImapSuccess_Message, Core.Domain.Enums.InfoBarMessageType.Success); - } - - private Task UpdateAccountAsync() - { - Account.Name = AccountName; - Account.SenderName = SenderName; - Account.AccountColorHex = SelectedColor == null ? string.Empty : SelectedColor.Hex; - - return _accountService.UpdateAccountAsync(Account); - } - - [RelayCommand] - private void ResetColor() - => SelectedColor = null; - - partial void OnSelectedColorChanged(AppColorViewModel oldValue, AppColorViewModel newValue) - { - _ = UpdateAccountAsync(); - } - - public override void OnNavigatedTo(NavigationMode mode, object parameters) - { - base.OnNavigatedTo(mode, parameters); - - if (parameters is MailAccount account) - { - Account = account; - AccountName = account.Name; - SenderName = account.SenderName; - ServerInformation = Account.ServerInformation; - - if (!string.IsNullOrEmpty(account.AccountColorHex)) - { - SelectedColor = AvailableColors.FirstOrDefault(a => a.Hex == account.AccountColorHex); - } - - if (ServerInformation != null) - { - SelectedIncomingServerAuthenticationMethodIndex = AvailableAuthenticationMethods.FindIndex(a => a.ImapAuthenticationMethod == ServerInformation.IncomingAuthenticationMethod); - SelectedIncomingServerConnectionSecurityIndex = AvailableConnectionSecurities.FindIndex(a => a.ImapConnectionSecurity == ServerInformation.IncomingServerSocketOption); - - SelectedOutgoingServerAuthenticationMethodIndex = AvailableAuthenticationMethods.FindIndex(a => a.ImapAuthenticationMethod == ServerInformation.OutgoingAuthenticationMethod); - SelectedOutgoingServerConnectionSecurityIndex = AvailableConnectionSecurities.FindIndex(a => a.ImapConnectionSecurity == ServerInformation.OutgoingServerSocketOption); - } - } - } -} diff --git a/Wino.Mail.WinUI/App.xaml.cs b/Wino.Mail.WinUI/App.xaml.cs index 24547a48..6a85f851 100644 --- a/Wino.Mail.WinUI/App.xaml.cs +++ b/Wino.Mail.WinUI/App.xaml.cs @@ -155,7 +155,6 @@ public partial class App : WinoApplication, services.AddTransient(typeof(ComposePageViewModel)); services.AddTransient(typeof(IdlePageViewModel)); - services.AddTransient(typeof(EditAccountDetailsPageViewModel)); services.AddTransient(typeof(ImapCalDavSettingsPageViewModel)); services.AddTransient(typeof(AccountDetailsPageViewModel)); services.AddTransient(typeof(SignatureManagementPageViewModel)); diff --git a/Wino.Mail.WinUI/Services/NavigationService.cs b/Wino.Mail.WinUI/Services/NavigationService.cs index 348defaf..1c183c65 100644 --- a/Wino.Mail.WinUI/Services/NavigationService.cs +++ b/Wino.Mail.WinUI/Services/NavigationService.cs @@ -16,8 +16,8 @@ using Wino.Mail.WinUI.Interfaces; using Wino.Mail.WinUI.Models; using Wino.Mail.WinUI.Services; using Wino.Mail.WinUI.Views.Calendar; -using Wino.Messaging.Client.Mails; using Wino.Messaging.Client.Calendar; +using Wino.Messaging.Client.Mails; using Wino.Messaging.Client.Navigation; using Wino.Views; using Wino.Views.Account; @@ -115,7 +115,6 @@ public class NavigationService : NavigationServiceBase, INavigationService WinoPage.AppPreferencesPage => typeof(AppPreferencesPage), WinoPage.AliasManagementPage => typeof(AliasManagementPage), WinoPage.LanguageTimePage => typeof(LanguageTimePage), - WinoPage.EditAccountDetailsPage => typeof(EditAccountDetailsPage), WinoPage.ImapCalDavSettingsPage => typeof(ImapCalDavSettingsPage), WinoPage.KeyboardShortcutsPage => typeof(KeyboardShortcutsPage), WinoPage.ContactsPage => typeof(ContactsPage), diff --git a/Wino.Mail.WinUI/Views/Abstract/EditAccountDetailsPageAbstract.cs b/Wino.Mail.WinUI/Views/Abstract/EditAccountDetailsPageAbstract.cs deleted file mode 100644 index 48dad69a..00000000 --- a/Wino.Mail.WinUI/Views/Abstract/EditAccountDetailsPageAbstract.cs +++ /dev/null @@ -1,5 +0,0 @@ -using Wino.Mail.WinUI; -using Wino.Mail.ViewModels; - -namespace Wino.Views.Abstract; -public partial class EditAccountDetailsPageAbstract : BasePage { } diff --git a/Wino.Mail.WinUI/Views/Account/AccountDetailsPage.xaml b/Wino.Mail.WinUI/Views/Account/AccountDetailsPage.xaml index 2e550af7..3b5ecaaa 100644 --- a/Wino.Mail.WinUI/Views/Account/AccountDetailsPage.xaml +++ b/Wino.Mail.WinUI/Views/Account/AccountDetailsPage.xaml @@ -2,11 +2,13 @@ x:Class="Wino.Views.AccountDetailsPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:accounts="using:Wino.Core.Domain.Models.Accounts" xmlns:abstract="using:Wino.Views.Abstract" xmlns:calendar="using:Wino.Core.Domain.Entities.Calendar" xmlns:controls="using:CommunityToolkit.WinUI.Controls" xmlns:controls1="using:Wino.Controls" xmlns:coreControls="using:Wino.Mail.WinUI.Controls" + xmlns:data="using:Wino.Core.ViewModels.Data" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:domain="using:Wino.Core.Domain" xmlns:folders="using:Wino.Core.Domain.Models.Folders" @@ -74,63 +76,278 @@ + - - - - - - - - - - - - - - - - - - - - + + + + + + - + + + + + + + + + + HorizontalContentAlignment="Stretch" + VerticalContentAlignment="Stretch" + ContentAlignment="Vertical" + Description="{x:Bind domain:Translator.AccountDetailsPage_ColorPicker_Description}" + Header="{x:Bind domain:Translator.AccountDetailsPage_ColorPicker_Title}"> + + + + + + + + + + + +