diff --git a/Wino.Mail.ViewModels/SignatureManagementPageViewModel.cs b/Wino.Mail.ViewModels/SignatureManagementPageViewModel.cs index 9e92ba6f..f67fdea9 100644 --- a/Wino.Mail.ViewModels/SignatureManagementPageViewModel.cs +++ b/Wino.Mail.ViewModels/SignatureManagementPageViewModel.cs @@ -20,47 +20,18 @@ public partial class SignatureManagementPageViewModel(IMailDialogService dialogS IAccountService accountService) : MailBaseViewModel { public ObservableCollection Signatures { get; set; } = []; + private bool isLoaded; [ObservableProperty] - private bool isSignatureEnabled; - - private int signatureForNewMessagesIndex; + public partial bool IsSignatureEnabled { get; set; } public Guid EmptyGuid { get; } = Guid.Empty; - public int SignatureForNewMessagesIndex - { - get => signatureForNewMessagesIndex; - set - { - if (value == -1) - { - SetProperty(ref signatureForNewMessagesIndex, 0); - } - else - { - SetProperty(ref signatureForNewMessagesIndex, value); - } - } - } + [ObservableProperty] + public partial AccountSignature SelectedSignatureForNewMessages { get; set; } - private int signatureForFollowingMessagesIndex; - - public int SignatureForFollowingMessagesIndex - { - get => signatureForFollowingMessagesIndex; - set - { - if (value == -1) - { - SetProperty(ref signatureForFollowingMessagesIndex, 0); - } - else - { - SetProperty(ref signatureForFollowingMessagesIndex, value); - } - } - } + [ObservableProperty] + public partial AccountSignature SelectedSignatureForFollowingMessages { get; set; } private MailAccount Account { get; set; } @@ -71,6 +42,7 @@ public partial class SignatureManagementPageViewModel(IMailDialogService dialogS public override async void OnNavigatedTo(NavigationMode mode, object parameters) { base.OnNavigatedTo(mode, parameters); + isLoaded = false; if (parameters is Guid accountId) Account = await _accountService.GetAccountAsync(accountId); @@ -78,36 +50,43 @@ public partial class SignatureManagementPageViewModel(IMailDialogService dialogS if (Account == null) return; var dbSignatures = await _signatureService.GetSignaturesAsync(Account.Id); - IsSignatureEnabled = Account.Preferences.IsSignatureEnabled; + var noneSignature = new AccountSignature { Id = EmptyGuid, Name = Translator.SettingsSignature_NoneSignatureName }; + var signatureForNewMessages = dbSignatures.FirstOrDefault(x => x.Id == Account.Preferences.SignatureIdForNewMessages) ?? noneSignature; + var signatureForFollowingMessages = dbSignatures.FirstOrDefault(x => x.Id == Account.Preferences.SignatureIdForFollowingMessages) ?? noneSignature; - Signatures.Clear(); - Signatures.Add(new AccountSignature { Id = EmptyGuid, Name = Translator.SettingsSignature_NoneSignatureName }); - dbSignatures.ForEach(Signatures.Add); + await ExecuteUIThread(() => + { + IsSignatureEnabled = Account.Preferences.IsSignatureEnabled; - SignatureForNewMessagesIndex = Signatures.IndexOf(Signatures.FirstOrDefault(x => x.Id == Account.Preferences.SignatureIdForNewMessages)); - SignatureForFollowingMessagesIndex = Signatures.IndexOf(Signatures.FirstOrDefault(x => x.Id == Account.Preferences.SignatureIdForFollowingMessages)); + Signatures.Clear(); + Signatures.Add(noneSignature); + dbSignatures.ForEach(Signatures.Add); + + SelectedSignatureForNewMessages = signatureForNewMessages; + SelectedSignatureForFollowingMessages = signatureForFollowingMessages; + }); + + isLoaded = true; } protected override async void OnPropertyChanged(PropertyChangedEventArgs e) { base.OnPropertyChanged(e); + if (!isLoaded || Account?.Preferences == null) return; + switch (e.PropertyName) { case nameof(IsSignatureEnabled): Account.Preferences.IsSignatureEnabled = IsSignatureEnabled; await _accountService.UpdateAccountAsync(Account); break; - case nameof(SignatureForNewMessagesIndex): - Account.Preferences.SignatureIdForNewMessages = SignatureForNewMessagesIndex > -1 - && Signatures[SignatureForNewMessagesIndex].Id != EmptyGuid - ? Signatures[SignatureForNewMessagesIndex].Id : null; + case nameof(SelectedSignatureForNewMessages): + Account.Preferences.SignatureIdForNewMessages = GetPersistedSignatureId(SelectedSignatureForNewMessages); await _accountService.UpdateAccountAsync(Account); break; - case nameof(SignatureForFollowingMessagesIndex): - Account.Preferences.SignatureIdForFollowingMessages = SignatureForFollowingMessagesIndex > -1 - && Signatures[SignatureForFollowingMessagesIndex].Id != EmptyGuid - ? Signatures[SignatureForFollowingMessagesIndex].Id : null; + case nameof(SelectedSignatureForFollowingMessages): + Account.Preferences.SignatureIdForFollowingMessages = GetPersistedSignatureId(SelectedSignatureForFollowingMessages); await _accountService.UpdateAccountAsync(Account); break; } @@ -121,7 +100,7 @@ public partial class SignatureManagementPageViewModel(IMailDialogService dialogS if (dialogResult == null) return; dialogResult.MailAccountId = Account.Id; - Signatures.Add(dialogResult); + await ExecuteUIThread(() => Signatures.Add(dialogResult)); await _signatureService.CreateSignatureAsync(dialogResult); } @@ -133,18 +112,23 @@ public partial class SignatureManagementPageViewModel(IMailDialogService dialogS if (dialogResult == null) return; var indexOfCurrentSignature = Signatures.IndexOf(signatureModel); - var signatureNewMessagesIndex = SignatureForNewMessagesIndex; - var signatureFollowingMessagesIndex = SignatureForFollowingMessagesIndex; + if (indexOfCurrentSignature < 0) return; - Signatures[indexOfCurrentSignature] = dialogResult; + var wasSelectedForNewMessages = SelectedSignatureForNewMessages?.Id == signatureModel.Id; + var wasSelectedForFollowingMessages = SelectedSignatureForFollowingMessages?.Id == signatureModel.Id; - // Reset selection to point updated signature. - // When Item updated/removed index switches to -1. We save index that was used before and update -1 to it. - if (signatureNewMessagesIndex == indexOfCurrentSignature) - SignatureForNewMessagesIndex = indexOfCurrentSignature; + dialogResult.MailAccountId = signatureModel.MailAccountId; - if (signatureFollowingMessagesIndex == indexOfCurrentSignature) - SignatureForFollowingMessagesIndex = indexOfCurrentSignature; + await ExecuteUIThread(() => + { + Signatures[indexOfCurrentSignature] = dialogResult; + + if (wasSelectedForNewMessages) + SelectedSignatureForNewMessages = dialogResult; + + if (wasSelectedForFollowingMessages) + SelectedSignatureForFollowingMessages = dialogResult; + }); await _signatureService.UpdateSignatureAsync(dialogResult); } @@ -156,7 +140,31 @@ public partial class SignatureManagementPageViewModel(IMailDialogService dialogS if (!shouldRemove) return; - Signatures.Remove(signatureModel); + var shouldResetNewMessagesSignature = SelectedSignatureForNewMessages?.Id == signatureModel.Id; + var shouldResetFollowingMessagesSignature = SelectedSignatureForFollowingMessages?.Id == signatureModel.Id; + + await ExecuteUIThread(() => + { + Signatures.Remove(signatureModel); + + var noneSignature = GetNoneSignature(); + + if (shouldResetNewMessagesSignature) + SelectedSignatureForNewMessages = noneSignature; + + if (shouldResetFollowingMessagesSignature) + SelectedSignatureForFollowingMessages = noneSignature; + }); + await _signatureService.DeleteSignatureAsync(signatureModel); } + + private Guid? GetPersistedSignatureId(AccountSignature signature) + => signature?.Id is Guid signatureId && signatureId != EmptyGuid + ? signatureId + : null; + + private AccountSignature GetNoneSignature() + => Signatures.FirstOrDefault(x => x.Id == EmptyGuid) + ?? new AccountSignature { Id = EmptyGuid, Name = Translator.SettingsSignature_NoneSignatureName }; } diff --git a/Wino.Mail.WinUI/Dialogs/SignatureEditorDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/SignatureEditorDialog.xaml.cs index 57870e68..6fb8d1a1 100644 --- a/Wino.Mail.WinUI/Dialogs/SignatureEditorDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/SignatureEditorDialog.xaml.cs @@ -1,5 +1,4 @@ using System; -using System.Text.RegularExpressions; using Microsoft.UI.Xaml.Controls; using Wino.Core.Domain; using Wino.Core.Domain.Entities.Mail; @@ -24,9 +23,6 @@ public sealed partial class SignatureEditorDialog : ContentDialog { InitializeComponent(); - SignatureNameTextBox.Text = signatureModel.Name.Trim(); - SignatureNameTextBox.Header = string.Format(Translator.SignatureEditorDialog_SignatureName_TitleEdit, signatureModel.Name); - Result = new AccountSignature { Id = signatureModel.Id, @@ -35,6 +31,9 @@ public sealed partial class SignatureEditorDialog : ContentDialog HtmlBody = signatureModel.HtmlBody }; + SignatureNameTextBox.Text = Result.Name.Trim(); + SignatureNameTextBox.Header = string.Format(Translator.SignatureEditorDialog_SignatureName_TitleEdit, Result.Name); + // TODO: Should be added additional logic to enable/disable primary button when webview content changed. IsPrimaryButtonEnabled = true; } @@ -51,7 +50,7 @@ public sealed partial class SignatureEditorDialog : ContentDialog private async void SaveClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args) { - var newSignature = Regex.Unescape((await WebViewEditor.GetHtmlBodyAsync())!); + var newSignature = await WebViewEditor.GetHtmlBodyAsync() ?? string.Empty; if (Result == null) { diff --git a/Wino.Mail.WinUI/Views/Settings/SignatureManagementPage.xaml b/Wino.Mail.WinUI/Views/Settings/SignatureManagementPage.xaml index 8589e400..11c4abdc 100644 --- a/Wino.Mail.WinUI/Views/Settings/SignatureManagementPage.xaml +++ b/Wino.Mail.WinUI/Views/Settings/SignatureManagementPage.xaml @@ -77,7 +77,7 @@ IsActionIconVisible="False" IsClickEnabled="False" IsEnabled="{x:Bind ViewModel.IsSignatureEnabled, Mode=OneWay}"> - + @@ -91,7 +91,7 @@ IsActionIconVisible="False" IsClickEnabled="False" IsEnabled="{x:Bind ViewModel.IsSignatureEnabled, Mode=OneWay}"> - +