CreateDefaultSignatureAsync(Guid accountId)
{
- return new AccountSignature()
+ var defaultSignature = new AccountSignature()
{
Id = Guid.NewGuid(),
+ MailAccountId = accountId,
+ // TODO: Should be translated?
+ Name = "Wino Default Signature",
HtmlBody = @"Sent from Wino Mail for Windows
"
};
+
+ await Connection.InsertAsync(defaultSignature);
+
+ return defaultSignature;
+ }
+
+ public async Task UpdateSignatureAsync(AccountSignature signature)
+ {
+ await Connection.UpdateAsync(signature);
+
+ return signature;
+ }
+
+ public async Task DeleteSignatureAsync(AccountSignature signature)
+ {
+ await Connection.DeleteAsync(signature);
+
+ return signature;
}
}
}
diff --git a/Wino.Mail.ViewModels/AccountDetailsPageViewModel.cs b/Wino.Mail.ViewModels/AccountDetailsPageViewModel.cs
index 1a60a282..8f373065 100644
--- a/Wino.Mail.ViewModels/AccountDetailsPageViewModel.cs
+++ b/Wino.Mail.ViewModels/AccountDetailsPageViewModel.cs
@@ -24,7 +24,7 @@ namespace Wino.Mail.ViewModels
private readonly IFolderService _folderService;
public MailAccount Account { get; set; }
- public ObservableCollection CurrentFolders { get; set; } = new ObservableCollection();
+ public ObservableCollection CurrentFolders { get; set; } = [];
[ObservableProperty]
private bool isFocusedInboxEnabled;
@@ -32,6 +32,9 @@ namespace Wino.Mail.ViewModels
[ObservableProperty]
private bool areNotificationsEnabled;
+ [ObservableProperty]
+ private bool isSignatureEnabled;
+
[ObservableProperty]
private bool isAppendMessageSettingVisible;
@@ -116,6 +119,7 @@ namespace Wino.Mail.ViewModels
IsFocusedInboxEnabled = Account.Preferences.IsFocusedInboxEnabled.GetValueOrDefault();
AreNotificationsEnabled = Account.Preferences.IsNotificationsEnabled;
+ IsSignatureEnabled = Account.Preferences.IsSignatureEnabled;
IsAppendMessageSettingVisible = Account.ProviderType == MailProviderType.IMAP4;
IsAppendMessageSettinEnabled = Account.Preferences.ShouldAppendMessagesToSentFolder;
@@ -135,23 +139,24 @@ namespace Wino.Mail.ViewModels
{
base.OnPropertyChanged(e);
- if (e.PropertyName == nameof(IsFocusedInboxEnabled) && IsFocusedInboxSupportedForAccount)
+ switch (e.PropertyName)
{
- Account.Preferences.IsFocusedInboxEnabled = IsFocusedInboxEnabled;
-
- await _accountService.UpdateAccountAsync(Account);
- }
- else if (e.PropertyName == nameof(AreNotificationsEnabled))
- {
- Account.Preferences.IsNotificationsEnabled = AreNotificationsEnabled;
-
- await _accountService.UpdateAccountAsync(Account);
- }
- else if (e.PropertyName == nameof(IsAppendMessageSettinEnabled))
- {
- Account.Preferences.ShouldAppendMessagesToSentFolder = IsAppendMessageSettinEnabled;
-
- await _accountService.UpdateAccountAsync(Account);
+ case nameof(IsFocusedInboxEnabled) when IsFocusedInboxSupportedForAccount:
+ Account.Preferences.IsFocusedInboxEnabled = IsFocusedInboxEnabled;
+ await _accountService.UpdateAccountAsync(Account);
+ break;
+ case nameof(AreNotificationsEnabled):
+ Account.Preferences.IsNotificationsEnabled = AreNotificationsEnabled;
+ await _accountService.UpdateAccountAsync(Account);
+ break;
+ case nameof(IsAppendMessageSettinEnabled):
+ Account.Preferences.ShouldAppendMessagesToSentFolder = IsAppendMessageSettinEnabled;
+ await _accountService.UpdateAccountAsync(Account);
+ break;
+ case nameof(IsSignatureEnabled):
+ Account.Preferences.IsSignatureEnabled = IsSignatureEnabled;
+ await _accountService.UpdateAccountAsync(Account);
+ break;
}
}
}
diff --git a/Wino.Mail.ViewModels/SignatureManagementPageViewModel.cs b/Wino.Mail.ViewModels/SignatureManagementPageViewModel.cs
index bd161bce..740999f6 100644
--- a/Wino.Mail.ViewModels/SignatureManagementPageViewModel.cs
+++ b/Wino.Mail.ViewModels/SignatureManagementPageViewModel.cs
@@ -1,57 +1,71 @@
using System;
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
-using CommunityToolkit.Mvvm.Messaging;
+using MoreLinq;
+using MoreLinq.Extensions;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
-using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Navigation;
-using Wino.Core.Domain.Models.Reader;
-using Wino.Core.Messages.Mails;
namespace Wino.Mail.ViewModels
{
- public partial class SignatureManagementPageViewModel : BaseViewModel
+ public partial class SignatureManagementPageViewModel(IDialogService dialogService,
+ ISignatureService signatureService,
+ IAccountService accountService) : BaseViewModel(dialogService)
{
- public Func> GetHTMLBodyFunction;
- public Func> GetTextBodyFunction;
-
- public List ToolbarSections { get; set; } = new List()
- {
- new EditorToolbarSection(){ SectionType = EditorToolbarSectionType.Format },
- new EditorToolbarSection(){ SectionType = EditorToolbarSectionType.Insert },
- };
-
- [ObservableProperty]
- private EditorToolbarSection selectedToolbarSection;
+ public ObservableCollection Signatures { get; set; } = [];
[ObservableProperty]
private bool isSignatureEnabled;
- public MailAccount Account { get; set; }
+ private int signatureForNewMessagesIndex;
- public AsyncRelayCommand SaveSignatureCommand { get; set; }
+ public Guid EmptyGuid { get; } = Guid.Empty;
- public INativeAppService NativeAppService { get; }
- private readonly ISignatureService _signatureService;
- private readonly IAccountService _accountService;
-
- public SignatureManagementPageViewModel(IDialogService dialogService,
- INativeAppService nativeAppService,
- ISignatureService signatureService,
- IAccountService accountService) : base(dialogService)
+ public int SignatureForNewMessagesIndex
{
- SelectedToolbarSection = ToolbarSections[0];
- NativeAppService = nativeAppService;
- _signatureService = signatureService;
- _accountService = accountService;
- SaveSignatureCommand = new AsyncRelayCommand(SaveSignatureAsync);
+ get => signatureForNewMessagesIndex;
+ set
+ {
+ if (value == -1)
+ {
+ SetProperty(ref signatureForNewMessagesIndex, 0);
+ }
+ else
+ {
+ SetProperty(ref signatureForNewMessagesIndex, value);
+ }
+ }
}
+ private int signatureForFollowingMessagesIndex;
+
+ public int SignatureForFollowingMessagesIndex
+ {
+ get => signatureForFollowingMessagesIndex;
+ set
+ {
+ if (value == -1)
+ {
+ SetProperty(ref signatureForFollowingMessagesIndex, 0);
+ }
+ else
+ {
+ SetProperty(ref signatureForFollowingMessagesIndex, value);
+ }
+ }
+ }
+
+ private MailAccount Account { get; set; }
+
+ private readonly ISignatureService _signatureService = signatureService;
+ private readonly IAccountService _accountService = accountService;
+
public override async void OnNavigatedTo(NavigationMode mode, object parameters)
{
base.OnNavigatedTo(mode, parameters);
@@ -59,35 +73,89 @@ namespace Wino.Mail.ViewModels
if (parameters is Guid accountId)
Account = await _accountService.GetAccountAsync(accountId);
- if (Account != null)
+ if (Account == null) return;
+
+ var dbSignatures = await _signatureService.GetSignaturesAsync(Account.Id);
+ IsSignatureEnabled = Account.Preferences.IsSignatureEnabled;
+
+ Signatures.Clear();
+ Signatures.Add(new AccountSignature { Id = EmptyGuid, Name = Translator.SettingsSignature_NoneSignatureName });
+ dbSignatures.ForEach(Signatures.Add);
+
+ SignatureForNewMessagesIndex = Signatures.IndexOf(Signatures.FirstOrDefault(x => x.Id == Account.Preferences.SignatureIdForNewMessages));
+ SignatureForFollowingMessagesIndex = Signatures.IndexOf(Signatures.FirstOrDefault(x => x.Id == Account.Preferences.SignatureIdForFollowingMessages));
+ }
+
+ protected override async void OnPropertyChanged(PropertyChangedEventArgs e)
+ {
+ base.OnPropertyChanged(e);
+
+ switch (e.PropertyName)
{
- var accountSignature = await _signatureService.GetAccountSignatureAsync(Account.Id);
-
- IsSignatureEnabled = accountSignature != null;
-
- if (IsSignatureEnabled)
- Messenger.Send(new HtmlRenderingRequested(accountSignature.HtmlBody));
- else
- Messenger.Send(new HtmlRenderingRequested(string.Empty)); // To get the theme changes. Render empty html.
+ 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;
+ await _accountService.UpdateAccountAsync(Account);
+ break;
+ case nameof(SignatureForFollowingMessagesIndex):
+ Account.Preferences.SignatureIdForFollowingMessages = SignatureForFollowingMessagesIndex > -1
+ && Signatures[SignatureForFollowingMessagesIndex].Id != EmptyGuid
+ ? Signatures[SignatureForFollowingMessagesIndex].Id : null;
+ await _accountService.UpdateAccountAsync(Account);
+ break;
}
}
- private async Task SaveSignatureAsync()
+ [RelayCommand]
+ private async Task OpenSignatureEditorCreateAsync()
{
- if (IsSignatureEnabled)
- {
- var newSignature = Regex.Unescape(await GetHTMLBodyFunction());
+ var dialogResult = await DialogService.ShowSignatureEditorDialog();
- await _signatureService.UpdateAccountSignatureAsync(Account.Id, newSignature);
+ if (dialogResult == null) return;
- DialogService.InfoBarMessage(Translator.Info_SignatureSavedTitle, Translator.Info_SignatureSavedMessage, Core.Domain.Enums.InfoBarMessageType.Success);
- }
- else
- {
- await _signatureService.DeleteAccountSignatureAssignment(Account.Id);
+ dialogResult.MailAccountId = Account.Id;
+ Signatures.Add(dialogResult);
+ await _signatureService.CreateSignatureAsync(dialogResult);
+ }
- DialogService.InfoBarMessage(Translator.Info_SignatureDisabledTitle, Translator.Info_SignatureDisabledMessage, Core.Domain.Enums.InfoBarMessageType.Success);
- }
+ [RelayCommand]
+ private async Task OpenSignatureEditorEditAsync(AccountSignature signatureModel)
+ {
+ var dialogResult = await DialogService.ShowSignatureEditorDialog(signatureModel);
+
+ if (dialogResult == null) return;
+
+ var indexOfCurrentSignature = Signatures.IndexOf(signatureModel);
+ var signatureNewMessagesIndex = SignatureForNewMessagesIndex;
+ var signatureFollowingMessagesIndex = SignatureForFollowingMessagesIndex;
+
+ Signatures[indexOfCurrentSignature] = dialogResult;
+
+ // 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;
+
+ if (signatureFollowingMessagesIndex == indexOfCurrentSignature)
+ SignatureForFollowingMessagesIndex = indexOfCurrentSignature;
+
+ await _signatureService.UpdateSignatureAsync(dialogResult);
+ }
+
+ [RelayCommand]
+ private async Task RemoveSignatureAsync(AccountSignature signatureModel)
+ {
+ var dialogResult = await DialogService.ShowConfirmationDialogAsync(string.Format(Translator.SignatureDeleteDialog_Message, signatureModel.Name), Translator.SignatureDeleteDialog_Title, Translator.Buttons_Delete);
+
+ if (!dialogResult) return;
+
+ Signatures.Remove(signatureModel);
+ await _signatureService.DeleteSignatureAsync(signatureModel);
}
}
}
diff --git a/Wino.Mail/Dialogs/SignatureEditorDialog.xaml b/Wino.Mail/Dialogs/SignatureEditorDialog.xaml
new file mode 100644
index 00000000..1665a12e
--- /dev/null
+++ b/Wino.Mail/Dialogs/SignatureEditorDialog.xaml
@@ -0,0 +1,266 @@
+
+
+
+ 1200
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Wino.Mail/Dialogs/SignatureEditorDialog.xaml.cs b/Wino.Mail/Dialogs/SignatureEditorDialog.xaml.cs
new file mode 100644
index 00000000..4aba25a4
--- /dev/null
+++ b/Wino.Mail/Dialogs/SignatureEditorDialog.xaml.cs
@@ -0,0 +1,373 @@
+using System;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Web.WebView2.Core;
+using Newtonsoft.Json;
+using Windows.UI.ViewManagement.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Wino.Core.Domain;
+using Wino.Core.Domain.Entities;
+using Wino.Core.Domain.Interfaces;
+using Wino.Core.Messages.Mails;
+using Wino.Views.Settings;
+
+namespace Wino.Dialogs
+{
+ public sealed partial class SignatureEditorDialog : ContentDialog
+ {
+ private Func> _getHTMLBodyFunction;
+ private readonly TaskCompletionSource _domLoadedTask = new TaskCompletionSource();
+ private readonly INativeAppService _nativeAppService = App.Current.Services.GetService();
+ public string SignatureNameHeader { get; set; }
+ public AccountSignature Result;
+
+ public bool IsComposerDarkMode
+ {
+ get { return (bool)GetValue(IsComposerDarkModeProperty); }
+ set { SetValue(IsComposerDarkModeProperty, value); }
+ }
+
+ public static readonly DependencyProperty IsComposerDarkModeProperty = DependencyProperty.Register(nameof(IsComposerDarkMode), typeof(bool), typeof(SignatureManagementPage), new PropertyMetadata(false, OnIsComposerDarkModeChanged));
+
+ public SignatureEditorDialog()
+ {
+ InitializeComponent();
+
+ SignatureNameHeader = Translator.SignatureEditorDialog_SignatureName_TitleNew;
+ Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--enable-features=OverlayScrollbar,OverlayScrollbarWinStyle,OverlayScrollbarWinStyleAnimation");
+
+ // TODO: Should be added additional logic to enable/disable primary button when webview content changed.
+ IsPrimaryButtonEnabled = true;
+ }
+
+ public SignatureEditorDialog(AccountSignature signatureModel)
+ {
+ InitializeComponent();
+
+ SignatureNameHeader = string.Format(Translator.SignatureEditorDialog_SignatureName_TitleEdit, signatureModel.Name);
+
+ Result = new AccountSignature
+ {
+ Id = signatureModel.Id,
+ Name = signatureModel.Name,
+ MailAccountId = signatureModel.MailAccountId,
+ HtmlBody = signatureModel.HtmlBody
+ };
+
+ Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--enable-features=OverlayScrollbar,OverlayScrollbarWinStyle,OverlayScrollbarWinStyleAnimation");
+
+ // TODO: Should be added additional logic to enable/disable primary button when webview content changed.
+ IsPrimaryButtonEnabled = true;
+ }
+
+ private async void SignatureDialogOpened(ContentDialog sender, ContentDialogOpenedEventArgs args)
+ {
+ Chromium.CoreWebView2Initialized -= ChromiumInitialized;
+ Chromium.CoreWebView2Initialized += ChromiumInitialized;
+
+ await Chromium.EnsureCoreWebView2Async();
+
+ _getHTMLBodyFunction = new Func>(async () =>
+ {
+ var quillContent = await InvokeScriptSafeAsync("GetHTMLContent();");
+
+ return JsonConvert.DeserializeObject(quillContent);
+ });
+
+ var underlyingThemeService = App.Current.Services.GetService();
+
+ IsComposerDarkMode = underlyingThemeService.IsUnderlyingThemeDark();
+
+ await RenderInternalAsync(Result?.HtmlBody ?? string.Empty);
+ }
+
+ private void DialogClosed(ContentDialog sender, ContentDialogClosedEventArgs args)
+ {
+ Chromium.CoreWebView2Initialized -= ChromiumInitialized;
+
+ if (Chromium.CoreWebView2 != null)
+ {
+ Chromium.CoreWebView2.DOMContentLoaded -= DOMLoaded;
+ Chromium.CoreWebView2.WebMessageReceived -= ScriptMessageRecieved;
+ }
+ }
+
+ private async void SaveClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
+ {
+ var newSignature = Regex.Unescape(await _getHTMLBodyFunction());
+
+ if (Result == null)
+ {
+ Result = new AccountSignature
+ {
+ Id = Guid.NewGuid(),
+ Name = SignatureNameTextBox.Text.Trim(),
+ HtmlBody = newSignature
+ };
+ }
+ else
+ {
+ Result.Name = SignatureNameTextBox.Text.Trim();
+ Result.HtmlBody = newSignature;
+ }
+
+ Hide();
+ }
+
+ private void CancelClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
+ {
+ Hide();
+ }
+
+ private async void HyperlinkAddClicked(object sender, RoutedEventArgs e)
+ {
+ await InvokeScriptSafeAsync($"addHyperlink('{LinkUrlTextBox.Text}')");
+
+ LinkUrlTextBox.Text = string.Empty;
+ HyperlinkFlyout.Hide();
+ }
+
+ private async void BoldButtonClicked(object sender, RoutedEventArgs e)
+ {
+ await InvokeScriptSafeAsync("document.getElementById('boldButton').click();");
+ }
+
+ private async void ItalicButtonClicked(object sender, RoutedEventArgs e)
+ {
+ await InvokeScriptSafeAsync("document.getElementById('italicButton').click();");
+ }
+
+ private async void UnderlineButtonClicked(object sender, RoutedEventArgs e)
+ {
+ await InvokeScriptSafeAsync("document.getElementById('underlineButton').click();");
+ }
+
+ private async void StrokeButtonClicked(object sender, RoutedEventArgs e)
+ {
+ await InvokeScriptSafeAsync("document.getElementById('strikeButton').click();");
+ }
+
+ private async void BulletListButtonClicked(object sender, RoutedEventArgs e)
+ {
+ await InvokeScriptSafeAsync("document.getElementById('bulletListButton').click();");
+ }
+
+ private async void OrderedListButtonClicked(object sender, RoutedEventArgs e)
+ {
+ await InvokeScriptSafeAsync("document.getElementById('orderedListButton').click();");
+ }
+
+ private async void IncreaseIndentClicked(object sender, RoutedEventArgs e)
+ {
+ await InvokeScriptSafeAsync("document.getElementById('increaseIndentButton').click();");
+ }
+
+ private async void DecreaseIndentClicked(object sender, RoutedEventArgs e)
+ {
+ await InvokeScriptSafeAsync("document.getElementById('decreaseIndentButton').click();");
+ }
+
+ private async void DirectionButtonClicked(object sender, RoutedEventArgs e)
+ {
+ await InvokeScriptSafeAsync("document.getElementById('directionButton').click();");
+ }
+
+ private async void AlignmentChanged(object sender, SelectionChangedEventArgs e)
+ {
+ var selectedItem = AlignmentListView.SelectedItem as ComboBoxItem;
+ var alignment = selectedItem.Tag.ToString();
+
+ switch (alignment)
+ {
+ case "left":
+ await InvokeScriptSafeAsync("document.getElementById('ql-align-left').click();");
+ break;
+ case "center":
+ await InvokeScriptSafeAsync("document.getElementById('ql-align-center').click();");
+ break;
+ case "right":
+ await InvokeScriptSafeAsync("document.getElementById('ql-align-right').click();");
+ break;
+ case "justify":
+ await InvokeScriptSafeAsync("document.getElementById('ql-align-justify').click();");
+ break;
+ }
+ }
+
+ public async Task ExecuteScriptFunctionAsync(string functionName, params object[] parameters)
+ {
+ string script = functionName + "(";
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ script += JsonConvert.SerializeObject(parameters[i]);
+ if (i < parameters.Length - 1)
+ {
+ script += ", ";
+ }
+ }
+ script += ");";
+
+ return await Chromium.ExecuteScriptAsync(script);
+ }
+
+ private async Task InvokeScriptSafeAsync(string function)
+ {
+ try
+ {
+ return await Chromium.ExecuteScriptAsync(function);
+ }
+ catch { }
+
+ return string.Empty;
+ }
+
+ private async void AddImageClicked(object sender, RoutedEventArgs e)
+ {
+ await InvokeScriptSafeAsync("document.getElementById('addImageButton').click();");
+ }
+
+ private async Task FocusEditorAsync()
+ {
+ await InvokeScriptSafeAsync("quill.focus();");
+
+ Chromium.Focus(FocusState.Keyboard);
+ Chromium.Focus(FocusState.Programmatic);
+ }
+
+ private async void EmojiButtonClicked(object sender, RoutedEventArgs e)
+ {
+ CoreInputView.GetForCurrentView().TryShow(CoreInputViewKind.Emoji);
+
+ await FocusEditorAsync();
+ }
+
+ private async Task TryGetSelectedTextAsync()
+ {
+ try
+ {
+ return await Chromium.ExecuteScriptAsync("getSelectedText();");
+ }
+ catch { }
+
+ return string.Empty;
+ }
+
+ private async void LinkButtonClicked(object sender, RoutedEventArgs e)
+ {
+ // Get selected text from Quill.
+
+ HyperlinkTextBox.Text = await TryGetSelectedTextAsync();
+ }
+
+ private async Task UpdateEditorThemeAsync()
+ {
+ await _domLoadedTask.Task;
+
+ if (IsComposerDarkMode)
+ {
+ await InvokeScriptSafeAsync("DarkReader.enable();");
+ }
+ else
+ {
+ await InvokeScriptSafeAsync("DarkReader.disable();");
+ }
+ }
+
+ private async Task RenderInternalAsync(string htmlBody)
+ {
+ await _domLoadedTask.Task;
+
+ await UpdateEditorThemeAsync();
+
+ if (string.IsNullOrEmpty(htmlBody))
+ {
+ await ExecuteScriptFunctionAsync("RenderHTML", " ");
+ }
+ else
+ {
+ await ExecuteScriptFunctionAsync("RenderHTML", htmlBody);
+
+ await FocusEditorAsync();
+ }
+ }
+
+ private async void ChromiumInitialized(Microsoft.UI.Xaml.Controls.WebView2 sender, Microsoft.UI.Xaml.Controls.CoreWebView2InitializedEventArgs args)
+ {
+ var editorBundlePath = (await _nativeAppService.GetQuillEditorBundlePathAsync()).Replace("full.html", string.Empty);
+
+ Chromium.CoreWebView2.SetVirtualHostNameToFolderMapping("app.example", editorBundlePath, CoreWebView2HostResourceAccessKind.Allow);
+ Chromium.Source = new Uri("https://app.example/full.html");
+
+ Chromium.CoreWebView2.DOMContentLoaded -= DOMLoaded;
+ Chromium.CoreWebView2.DOMContentLoaded += DOMLoaded;
+
+ Chromium.CoreWebView2.WebMessageReceived -= ScriptMessageRecieved;
+ Chromium.CoreWebView2.WebMessageReceived += ScriptMessageRecieved;
+ }
+
+ private static async void OnIsComposerDarkModeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
+ {
+ //if (obj is ComposePage page)
+ //{
+ // await page.UpdateEditorThemeAsync();
+ //}
+ }
+
+ private void ScriptMessageRecieved(CoreWebView2 sender, CoreWebView2WebMessageReceivedEventArgs args)
+ {
+ var change = JsonConvert.DeserializeObject(args.WebMessageAsJson);
+
+ bool isEnabled = change.EndsWith("ql-active");
+
+ if (change.StartsWith("ql-bold"))
+ BoldButton.IsFocusEngaged = isEnabled;
+ else if (change.StartsWith("ql-italic"))
+ ItalicButton.IsEnabled = isEnabled;
+ else if (change.StartsWith("ql-underline"))
+ UnderlineButton.IsEnabled = isEnabled;
+ else if (change.StartsWith("ql-strike"))
+ StrokeButton.IsEnabled = isEnabled;
+ else if (change.StartsWith("orderedListButton"))
+ OrderedListButton.IsChecked = isEnabled;
+ else if (change.StartsWith("bulletListButton"))
+ BulletListButton.IsChecked = isEnabled;
+ else if (change.StartsWith("ql-direction"))
+ DirectionButton.IsChecked = isEnabled;
+ else if (change.StartsWith("ql-align-left"))
+ {
+ AlignmentListView.SelectionChanged -= AlignmentChanged;
+ AlignmentListView.SelectedIndex = 0;
+ AlignmentListView.SelectionChanged += AlignmentChanged;
+ }
+ else if (change.StartsWith("ql-align-center"))
+ {
+ AlignmentListView.SelectionChanged -= AlignmentChanged;
+ AlignmentListView.SelectedIndex = 1;
+ AlignmentListView.SelectionChanged += AlignmentChanged;
+ }
+ else if (change.StartsWith("ql-align-right"))
+ {
+ AlignmentListView.SelectionChanged -= AlignmentChanged;
+ AlignmentListView.SelectedIndex = 2;
+ AlignmentListView.SelectionChanged += AlignmentChanged;
+ }
+ else if (change.StartsWith("ql-align-justify"))
+ {
+ AlignmentListView.SelectionChanged -= AlignmentChanged;
+ AlignmentListView.SelectedIndex = 3;
+ AlignmentListView.SelectionChanged += AlignmentChanged;
+ }
+ }
+
+ private void DOMLoaded(CoreWebView2 sender, CoreWebView2DOMContentLoadedEventArgs args) => _domLoadedTask.TrySetResult(true);
+
+ public async void Receive(HtmlRenderingRequested message)
+ {
+ await RenderInternalAsync(message.HtmlBody);
+ }
+
+ private void SignatureNameTextBoxTextChanged(object sender, TextChangedEventArgs e) => IsPrimaryButtonEnabled = !string.IsNullOrWhiteSpace(SignatureNameTextBox.Text);
+ }
+}
diff --git a/Wino.Mail/Services/DialogService.cs b/Wino.Mail/Services/DialogService.cs
index e38ba569..509d5ba8 100644
--- a/Wino.Mail/Services/DialogService.cs
+++ b/Wino.Mail/Services/DialogService.cs
@@ -331,6 +331,27 @@ namespace Wino.Services
return accountPicker.PickedAccount;
}
+ public async Task ShowSignatureEditorDialog(AccountSignature signatureModel = null)
+ {
+ SignatureEditorDialog signatureEditorDialog;
+ if (signatureModel != null)
+ {
+ signatureEditorDialog = new SignatureEditorDialog(signatureModel)
+ {
+ RequestedTheme = _themeService.RootTheme.ToWindowsElementTheme()
+ };
+ }
+ else
+ {
+ signatureEditorDialog = new SignatureEditorDialog()
+ {
+ RequestedTheme = _themeService.RootTheme.ToWindowsElementTheme()
+ };
+ }
+ var result = await HandleDialogPresentationAsync(signatureEditorDialog);
+
+ return result == ContentDialogResult.Primary ? signatureEditorDialog.Result : null;
+ }
}
}
diff --git a/Wino.Mail/Views/Account/AccountDetailsPage.xaml b/Wino.Mail/Views/Account/AccountDetailsPage.xaml
index 3deac2d1..f48bc48c 100644
--- a/Wino.Mail/Views/Account/AccountDetailsPage.xaml
+++ b/Wino.Mail/Views/Account/AccountDetailsPage.xaml
@@ -3,27 +3,27 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:abstract="using:Wino.Views.Abstract"
- xmlns:local="using:Wino.Views"
- xmlns:helpers="using:Wino.Helpers"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
- xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
+ xmlns:controls1="using:Wino.Controls"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:domain="using:Wino.Core.Domain"
+ xmlns:folders="using:Wino.Core.Domain.Models.Folders"
+ xmlns:helpers="using:Wino.Helpers"
xmlns:interactionsCore="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
- xmlns:controls1="using:Wino.Controls"
xmlns:interfaces="using:Wino.Core.Domain.Interfaces"
- xmlns:folders="using:Wino.Core.Domain.Models.Folders"
+ xmlns:local="using:Wino.Views"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
x:Name="root"
mc:Ignorable="d">
+ ItemsSource="{x:Bind ChildFolders}">
@@ -43,25 +43,25 @@
+ IsChecked="{x:Bind IsSynchronizationEnabled, Mode=OneWay}"
+ Tag="{Binding}"
+ Unchecked="SyncFolderToggled"
+ Visibility="{x:Bind IsMoveTarget}" />
+ IsChecked="{x:Bind ShowUnreadCount, Mode=OneWay}"
+ Tag="{Binding}"
+ Unchecked="UnreadBadgeCheckboxToggled"
+ Visibility="{x:Bind IsMoveTarget}" />
@@ -70,25 +70,25 @@
-
+
-
+
-
+
+ Header="{x:Bind domain:Translator.SettingsConfigureSpecialFolders_Title}"
+ IsActionIconVisible="True">
-
+
+ TextWrapping="Wrap" />
@@ -152,16 +152,17 @@
-->
+ Description="{x:Bind domain:Translator.SettingsSignature_Description}"
+ Header="{x:Bind domain:Translator.SettingsSignature_Title}"
+ IsClickEnabled="True">
+
-
+
@@ -169,9 +170,9 @@
+ Visibility="{x:Bind ViewModel.IsFocusedInboxSupportedForAccount, Mode=OneWay}">
@@ -180,29 +181,29 @@
+ Visibility="{x:Bind ViewModel.IsAppendMessageSettingVisible, Mode=OneWay}">
+ Data="F1 M 0 5.625 C 0 4.850261 0.148112 4.121094 0.444336 3.4375 C 0.74056 2.753906 1.142578 2.158203 1.650391 1.650391 C 2.158203 1.142578 2.753906 0.740561 3.4375 0.444336 C 4.121094 0.148113 4.85026 0 5.625 0 C 6.139323 0 6.635742 0.066732 7.114258 0.200195 C 7.592773 0.33366 8.040364 0.522461 8.457031 0.766602 C 8.873697 1.010742 9.254557 1.30534 9.599609 1.650391 C 9.944661 1.995443 10.239258 2.376303 10.483398 2.792969 C 10.727539 3.209637 10.916341 3.657227 11.049805 4.135742 C 11.183268 4.614259 11.25 5.110678 11.25 5.625 C 11.25 6.39974 11.101888 7.128907 10.805664 7.8125 C 10.509439 8.496094 10.107422 9.091797 9.599609 9.599609 C 9.091797 10.107422 8.496094 10.50944 7.8125 10.805664 C 7.128906 11.101889 6.399739 11.25 5.625 11.25 C 4.84375 11.25 4.111328 11.103516 3.427734 10.810547 C 2.744141 10.517578 2.148438 10.117188 1.640625 9.609375 C 1.132812 9.101562 0.732422 8.505859 0.439453 7.822266 C 0.146484 7.138672 0 6.40625 0 5.625 Z M 10.566406 15 C 10.214844 15 9.874674 14.936523 9.545898 14.80957 C 9.217122 14.682617 8.917643 14.510092 8.647461 14.291992 C 8.377278 14.073894 8.147786 13.815104 7.958984 13.515625 C 7.770182 13.216146 7.639974 12.893881 7.568359 12.548828 C 7.972005 12.431641 8.369141 12.278646 8.759766 12.089844 C 8.785807 12.324219 8.852539 12.542318 8.959961 12.744141 C 9.067383 12.945964 9.205729 13.121745 9.375 13.271484 C 9.544271 13.421225 9.736328 13.538412 9.951172 13.623047 C 10.166016 13.707683 10.390625 13.75 10.625 13.75 L 15.625 13.75 C 15.878906 13.75 16.119791 13.701172 16.347656 13.603516 C 16.57552 13.505859 16.775715 13.370769 16.948242 13.198242 C 17.120768 13.025717 17.255859 12.825521 17.353516 12.597656 C 17.451172 12.369792 17.5 12.128906 17.5 11.875 L 17.5 4.375 C 17.5 4.121094 17.451172 3.880209 17.353516 3.652344 C 17.255859 3.42448 17.120768 3.224285 16.948242 3.051758 C 16.775715 2.879232 16.57552 2.744141 16.347656 2.646484 C 16.119791 2.548828 15.878906 2.5 15.625 2.5 L 12.099609 2.5 C 11.988932 2.278646 11.870117 2.063803 11.743164 1.855469 C 11.616211 1.647137 11.477864 1.445312 11.328125 1.25 L 15.693359 1.25 C 16.103516 1.25 16.494141 1.333008 16.865234 1.499023 C 17.236328 1.665039 17.560221 1.886395 17.836914 2.163086 C 18.113605 2.439779 18.334961 2.763672 18.500977 3.134766 C 18.666992 3.505859 18.75 3.896484 18.75 4.306641 L 18.75 11.943359 C 18.75 12.353516 18.666992 12.744141 18.500977 13.115234 C 18.334961 13.486328 18.113605 13.810222 17.836914 14.086914 C 17.560221 14.363607 17.236328 14.584961 16.865234 14.750977 C 16.494141 14.916992 16.103516 15 15.693359 15 Z M 5.625 8.828125 C 5.820312 8.828125 5.986328 8.759766 6.123047 8.623047 L 8.623047 6.123047 C 8.759766 5.986328 8.828125 5.820312 8.828125 5.625 C 8.828125 5.429688 8.759766 5.263672 8.623047 5.126953 L 6.123047 2.626953 C 5.986328 2.490234 5.820312 2.421875 5.625 2.421875 C 5.429688 2.421875 5.263672 2.490234 5.126953 2.626953 C 4.990234 2.763672 4.921875 2.929688 4.921875 3.125 C 4.921875 3.320312 4.990234 3.486328 5.126953 3.623047 L 6.503906 5 L 3.125 5 C 2.955729 5.000001 2.809245 5.06185 2.685547 5.185547 C 2.561849 5.309245 2.5 5.455729 2.5 5.625 C 2.5 5.794271 2.561849 5.940756 2.685547 6.064453 C 2.809245 6.188151 2.955729 6.25 3.125 6.25 L 6.503906 6.25 L 5.126953 7.626953 C 4.990234 7.763672 4.921875 7.929688 4.921875 8.125 C 4.921875 8.320312 4.990234 8.486328 5.126953 8.623047 C 5.263672 8.759766 5.429688 8.828125 5.625 8.828125 Z M 4.306641 18.75 C 3.896484 18.75 3.505859 18.666992 3.134766 18.500977 C 2.763672 18.334961 2.439779 18.113607 2.163086 17.836914 C 1.886393 17.560221 1.665039 17.236328 1.499023 16.865234 C 1.333008 16.494141 1.25 16.103516 1.25 15.693359 L 1.25 11.328125 C 1.445312 11.477865 1.647135 11.616211 1.855469 11.743164 C 2.063802 11.870117 2.278646 11.988933 2.5 12.099609 L 2.5 15.625 C 2.5 15.878906 2.548828 16.119791 2.646484 16.347656 C 2.744141 16.575521 2.879232 16.775717 3.051758 16.948242 C 3.224284 17.120768 3.424479 17.255859 3.652344 17.353516 C 3.880208 17.451172 4.121094 17.5 4.375 17.5 L 9.375 17.5 C 9.576822 17.5 9.76888 17.470703 9.951172 17.412109 C 10.133463 17.353516 10.302734 17.268881 10.458984 17.158203 C 10.615234 17.047525 10.751953 16.915689 10.869141 16.762695 C 10.986328 16.609701 11.077474 16.438803 11.142578 16.25 L 12.441406 16.25 C 12.369791 16.608072 12.237955 16.940104 12.045898 17.246094 C 11.853841 17.552084 11.621094 17.815756 11.347656 18.037109 C 11.074219 18.258463 10.768229 18.432617 10.429688 18.55957 C 10.091146 18.686523 9.739583 18.75 9.375 18.75 Z " />
+ Command="{x:Bind ViewModel.DeleteAccountCommand}"
+ Description="{x:Bind domain:Translator.SettingsDeleteAccount_Description}"
+ Header="{x:Bind domain:Translator.SettingsDeleteAccount_Title}">
+ Content="{x:Bind domain:Translator.Buttons_Delete}" />
diff --git a/Wino.Mail/Views/Settings/SignatureManagementPage.xaml b/Wino.Mail/Views/Settings/SignatureManagementPage.xaml
index 5c9c0f7f..3b7b898e 100644
--- a/Wino.Mail/Views/Settings/SignatureManagementPage.xaml
+++ b/Wino.Mail/Views/Settings/SignatureManagementPage.xaml
@@ -3,282 +3,115 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:abstract="using:Wino.Views.Abstract"
- xmlns:helpers="using:Wino.Helpers"
- xmlns:domain="using:Wino.Core.Domain"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:controls="using:Wino.Controls"
xmlns:controls1="using:CommunityToolkit.WinUI.Controls"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:domain="using:Wino.Core.Domain"
+ xmlns:entities="using:Wino.Core.Domain.Entities"
+ xmlns:helpers="using:Wino.Helpers"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:reader="using:Wino.Core.Domain.Models.Reader"
+ x:Name="root"
mc:Ignorable="d">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/Wino.Mail/Views/Settings/SignatureManagementPage.xaml.cs b/Wino.Mail/Views/Settings/SignatureManagementPage.xaml.cs
index 571eaf8a..bdb61469 100644
--- a/Wino.Mail/Views/Settings/SignatureManagementPage.xaml.cs
+++ b/Wino.Mail/Views/Settings/SignatureManagementPage.xaml.cs
@@ -1,320 +1,12 @@
-using System;
-using System.Threading.Tasks;
-using CommunityToolkit.Mvvm.Messaging;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Web.WebView2.Core;
-using Newtonsoft.Json;
-using Windows.UI.ViewManagement.Core;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Navigation;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Messages.Mails;
-using Wino.Views.Abstract;
+using Wino.Views.Abstract;
namespace Wino.Views.Settings
{
- public sealed partial class SignatureManagementPage : SignatureManagementPageAbstract, IRecipient
+ public sealed partial class SignatureManagementPage : SignatureManagementPageAbstract
{
- private TaskCompletionSource DOMLoadedTask = new TaskCompletionSource();
-
- public bool IsComposerDarkMode
- {
- get { return (bool)GetValue(IsComposerDarkModeProperty); }
- set { SetValue(IsComposerDarkModeProperty, value); }
- }
-
- public static readonly DependencyProperty IsComposerDarkModeProperty = DependencyProperty.Register(nameof(IsComposerDarkMode), typeof(bool), typeof(SignatureManagementPage), new PropertyMetadata(false, OnIsComposerDarkModeChanged));
-
public SignatureManagementPage()
{
this.InitializeComponent();
-
- // Environment.SetEnvironmentVariable("WEBVIEW2_DEFAULT_BACKGROUND_COLOR", "00FFFFFF");
- Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--enable-features=OverlayScrollbar,OverlayScrollbarWinStyle,OverlayScrollbarWinStyleAnimation");
- }
-
- protected override void OnNavigatedFrom(NavigationEventArgs e)
- {
- base.OnNavigatedFrom(e);
-
- Chromium.CoreWebView2Initialized -= ChromiumInitialized;
-
- if (Chromium.CoreWebView2 != null)
- {
- Chromium.CoreWebView2.DOMContentLoaded -= DOMLoaded;
- Chromium.CoreWebView2.WebMessageReceived -= ScriptMessageRecieved;
- }
- }
-
- protected override async void OnNavigatedTo(NavigationEventArgs e)
- {
- base.OnNavigatedTo(e);
-
- Chromium.CoreWebView2Initialized -= ChromiumInitialized;
- Chromium.CoreWebView2Initialized += ChromiumInitialized;
-
- await Chromium.EnsureCoreWebView2Async();
-
- ViewModel.GetHTMLBodyFunction = new Func>(async () =>
- {
- var quillContent = await InvokeScriptSafeAsync("GetHTMLContent();");
-
- return JsonConvert.DeserializeObject(quillContent);
- });
-
- ViewModel.GetTextBodyFunction = new Func>(() => InvokeScriptSafeAsync("GetTextContent();"));
-
- var underlyingThemeService = App.Current.Services.GetService();
-
- IsComposerDarkMode = underlyingThemeService.IsUnderlyingThemeDark();
- }
-
- private async void HyperlinkAddClicked(object sender, RoutedEventArgs e)
- {
- await InvokeScriptSafeAsync($"addHyperlink('{LinkUrlTextBox.Text}')");
-
- LinkUrlTextBox.Text = string.Empty;
- HyperlinkFlyout.Hide();
- }
-
- private async void BoldButtonClicked(object sender, RoutedEventArgs e)
- {
- await InvokeScriptSafeAsync("document.getElementById('boldButton').click();");
- }
-
- private async void ItalicButtonClicked(object sender, RoutedEventArgs e)
- {
- await InvokeScriptSafeAsync("document.getElementById('italicButton').click();");
- }
-
- private async void UnderlineButtonClicked(object sender, RoutedEventArgs e)
- {
- await InvokeScriptSafeAsync("document.getElementById('underlineButton').click();");
- }
-
- private async void StrokeButtonClicked(object sender, RoutedEventArgs e)
- {
- await InvokeScriptSafeAsync("document.getElementById('strikeButton').click();");
- }
-
- private async void BulletListButtonClicked(object sender, RoutedEventArgs e)
- {
- await InvokeScriptSafeAsync("document.getElementById('bulletListButton').click();");
- }
-
- private async void OrderedListButtonClicked(object sender, RoutedEventArgs e)
- {
- await InvokeScriptSafeAsync("document.getElementById('orderedListButton').click();");
- }
-
- private async void IncreaseIndentClicked(object sender, RoutedEventArgs e)
- {
- await InvokeScriptSafeAsync("document.getElementById('increaseIndentButton').click();");
- }
-
- private async void DecreaseIndentClicked(object sender, RoutedEventArgs e)
- {
- await InvokeScriptSafeAsync("document.getElementById('decreaseIndentButton').click();");
- }
-
- private async void DirectionButtonClicked(object sender, RoutedEventArgs e)
- {
- await InvokeScriptSafeAsync("document.getElementById('directionButton').click();");
- }
-
- private async void AlignmentChanged(object sender, SelectionChangedEventArgs e)
- {
- var selectedItem = AlignmentListView.SelectedItem as ComboBoxItem;
- var alignment = selectedItem.Tag.ToString();
-
- switch (alignment)
- {
- case "left":
- await InvokeScriptSafeAsync("document.getElementById('ql-align-left').click();");
- break;
- case "center":
- await InvokeScriptSafeAsync("document.getElementById('ql-align-center').click();");
- break;
- case "right":
- await InvokeScriptSafeAsync("document.getElementById('ql-align-right').click();");
- break;
- case "justify":
- await InvokeScriptSafeAsync("document.getElementById('ql-align-justify').click();");
- break;
- }
- }
-
- public async Task ExecuteScriptFunctionAsync(string functionName, params object[] parameters)
- {
- string script = functionName + "(";
- for (int i = 0; i < parameters.Length; i++)
- {
- script += JsonConvert.SerializeObject(parameters[i]);
- if (i < parameters.Length - 1)
- {
- script += ", ";
- }
- }
- script += ");";
-
- return await Chromium.ExecuteScriptAsync(script);
- }
-
- private async Task InvokeScriptSafeAsync(string function)
- {
- try
- {
- return await Chromium.ExecuteScriptAsync(function);
- }
- catch (Exception) { }
-
- return string.Empty;
- }
-
- private async void AddImageClicked(object sender, RoutedEventArgs e)
- {
- await InvokeScriptSafeAsync("document.getElementById('addImageButton').click();");
- }
-
- private async Task FocusEditorAsync()
- {
- await InvokeScriptSafeAsync("quill.focus();");
-
- Chromium.Focus(FocusState.Keyboard);
- Chromium.Focus(FocusState.Programmatic);
- }
-
- private async void EmojiButtonClicked(object sender, RoutedEventArgs e)
- {
- CoreInputView.GetForCurrentView().TryShow(CoreInputViewKind.Emoji);
-
- await FocusEditorAsync();
- }
-
- private async Task TryGetSelectedTextAsync()
- {
- try
- {
- return await Chromium.ExecuteScriptAsync("getSelectedText();");
- }
- catch (Exception) { }
-
- return string.Empty;
- }
-
- private async void LinkButtonClicked(object sender, RoutedEventArgs e)
- {
- // Get selected text from Quill.
-
- HyperlinkTextBox.Text = await TryGetSelectedTextAsync();
- }
-
- private async Task UpdateEditorThemeAsync()
- {
- await DOMLoadedTask.Task;
-
- if (IsComposerDarkMode)
- {
- await InvokeScriptSafeAsync("DarkReader.enable();");
- }
- else
- {
- await InvokeScriptSafeAsync("DarkReader.disable();");
- }
- }
-
- private async Task RenderInternalAsync(string htmlBody)
- {
- await DOMLoadedTask.Task;
-
- await UpdateEditorThemeAsync();
-
- if (string.IsNullOrEmpty(htmlBody))
- {
- await ExecuteScriptFunctionAsync("RenderHTML", " ");
- }
- else
- {
- await ExecuteScriptFunctionAsync("RenderHTML", htmlBody);
-
- await FocusEditorAsync();
- }
- }
-
- private async void ChromiumInitialized(Microsoft.UI.Xaml.Controls.WebView2 sender, Microsoft.UI.Xaml.Controls.CoreWebView2InitializedEventArgs args)
- {
- var editorBundlePath = (await ViewModel.NativeAppService.GetQuillEditorBundlePathAsync()).Replace("full.html", string.Empty);
-
- Chromium.CoreWebView2.SetVirtualHostNameToFolderMapping("app.example", editorBundlePath, CoreWebView2HostResourceAccessKind.Allow);
- Chromium.Source = new Uri("https://app.example/full.html");
-
- Chromium.CoreWebView2.DOMContentLoaded -= DOMLoaded;
- Chromium.CoreWebView2.DOMContentLoaded += DOMLoaded;
-
- Chromium.CoreWebView2.WebMessageReceived -= ScriptMessageRecieved;
- Chromium.CoreWebView2.WebMessageReceived += ScriptMessageRecieved;
- }
-
- private static async void OnIsComposerDarkModeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
- {
- if (obj is ComposePage page)
- {
- await page.UpdateEditorThemeAsync();
- }
- }
-
- private void ScriptMessageRecieved(CoreWebView2 sender, CoreWebView2WebMessageReceivedEventArgs args)
- {
- var change = JsonConvert.DeserializeObject(args.WebMessageAsJson);
-
- bool isEnabled = change.EndsWith("ql-active");
-
- if (change.StartsWith("ql-bold"))
- BoldButton.IsChecked = isEnabled;
- else if (change.StartsWith("ql-italic"))
- ItalicButton.IsChecked = isEnabled;
- else if (change.StartsWith("ql-underline"))
- UnderlineButton.IsChecked = isEnabled;
- else if (change.StartsWith("ql-strike"))
- StrokeButton.IsChecked = isEnabled;
- else if (change.StartsWith("orderedListButton"))
- OrderedListButton.IsChecked = isEnabled;
- else if (change.StartsWith("bulletListButton"))
- BulletListButton.IsChecked = isEnabled;
- else if (change.StartsWith("ql-direction"))
- DirectionButton.IsChecked = isEnabled;
- else if (change.StartsWith("ql-align-left"))
- {
- AlignmentListView.SelectionChanged -= AlignmentChanged;
- AlignmentListView.SelectedIndex = 0;
- AlignmentListView.SelectionChanged += AlignmentChanged;
- }
- else if (change.StartsWith("ql-align-center"))
- {
- AlignmentListView.SelectionChanged -= AlignmentChanged;
- AlignmentListView.SelectedIndex = 1;
- AlignmentListView.SelectionChanged += AlignmentChanged;
- }
- else if (change.StartsWith("ql-align-right"))
- {
- AlignmentListView.SelectionChanged -= AlignmentChanged;
- AlignmentListView.SelectedIndex = 2;
- AlignmentListView.SelectionChanged += AlignmentChanged;
- }
- else if (change.StartsWith("ql-align-justify"))
- {
- AlignmentListView.SelectionChanged -= AlignmentChanged;
- AlignmentListView.SelectedIndex = 3;
- AlignmentListView.SelectionChanged += AlignmentChanged;
- }
- }
-
- private void DOMLoaded(CoreWebView2 sender, CoreWebView2DOMContentLoadedEventArgs args) => DOMLoadedTask.TrySetResult(true);
-
- public async void Receive(HtmlRenderingRequested message)
- {
- await RenderInternalAsync(message.HtmlBody);
}
}
}
diff --git a/Wino.Mail/Wino.Mail.csproj b/Wino.Mail/Wino.Mail.csproj
index c27cf3d5..0c1792c4 100644
--- a/Wino.Mail/Wino.Mail.csproj
+++ b/Wino.Mail/Wino.Mail.csproj
@@ -259,6 +259,9 @@
MoveMailDialog.xaml
+
+ SignatureEditorDialog.xaml
+
NewImapSetupDialog.xaml
@@ -492,6 +495,10 @@
Designer
MSBuild:Compile
+
+ MSBuild:Compile
+ Designer
+
Designer
MSBuild:Compile