Improve mailto links handling (#310)

* Refactor draft creation

* try scoped namespace

* Refactor mailto protocol and revert namespaces

* Remove useless account query

* Fix typo and CC/BCC in replies

* Replace convert with existing extension

* Small fixes

* Fix CC/Bcc in replies to automatically show if needed.

* Fixed body parameter position from mailto parameters

* Fixed issue with ReplyAll self not removed
This commit is contained in:
Tiktack
2024-08-10 14:33:02 +02:00
committed by GitHub
parent 8763bf11ab
commit f408f59beb
20 changed files with 360 additions and 377 deletions

View File

@@ -302,7 +302,7 @@ namespace Wino.Mail.ViewModels
}
else
{
bool hasMailtoActivation = _launchProtocolService.MailtoParameters != null;
bool hasMailtoActivation = _launchProtocolService.MailToUri != null;
if (hasMailtoActivation)
{
@@ -774,16 +774,13 @@ namespace Wino.Mail.ViewModels
var draftOptions = new DraftCreationOptions
{
Reason = DraftCreationReason.Empty,
// Include mail to parameters for parsing mailto if any.
MailtoParameters = _launchProtocolService.MailtoParameters
MailToUri = _launchProtocolService.MailToUri
};
var createdBase64EncodedMimeMessage = await _mailService.CreateDraftMimeBase64Async(account.Id, draftOptions).ConfigureAwait(false);
var createdDraftMailMessage = await _mailService.CreateDraftAsync(account, createdBase64EncodedMimeMessage).ConfigureAwait(false);
var (draftMailCopy, draftBase64MimeMessage) = await _mailService.CreateDraftAsync(account, draftOptions).ConfigureAwait(false);
var draftPreperationRequest = new DraftPreperationRequest(account, createdDraftMailMessage, createdBase64EncodedMimeMessage);
await _winoRequestDelegator.ExecuteAsync(draftPreperationRequest);
var draftPreparationRequest = new DraftPreparationRequest(account, draftMailCopy, draftBase64MimeMessage);
await _winoRequestDelegator.ExecuteAsync(draftPreparationRequest);
}
protected override async void OnAccountUpdated(MailAccount updatedAccount)

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
@@ -58,7 +57,7 @@ namespace Wino.Mail.ViewModels
private MessageImportance selectedMessageImportance;
[ObservableProperty]
private bool isCCBCCVisible = true;
private bool isCCBCCVisible;
[ObservableProperty]
private string subject;
@@ -77,21 +76,20 @@ namespace Wino.Mail.ViewModels
[ObservableProperty]
private bool isDraggingOverImagesDropZone;
public ObservableCollection<MailAttachmentViewModel> IncludedAttachments { get; set; } = new ObservableCollection<MailAttachmentViewModel>();
public ObservableCollection<MailAccount> Accounts { get; set; } = new ObservableCollection<MailAccount>();
public ObservableCollection<AddressInformation> ToItems { get; set; } = new ObservableCollection<AddressInformation>();
public ObservableCollection<AddressInformation> CCItemsItems { get; set; } = new ObservableCollection<AddressInformation>();
public ObservableCollection<AddressInformation> BCCItems { get; set; } = new ObservableCollection<AddressInformation>();
public ObservableCollection<MailAttachmentViewModel> IncludedAttachments { get; set; } = [];
public ObservableCollection<MailAccount> Accounts { get; set; } = [];
public ObservableCollection<AddressInformation> ToItems { get; set; } = [];
public ObservableCollection<AddressInformation> CCItems { get; set; } = [];
public ObservableCollection<AddressInformation> BCCItems { get; set; } = [];
public List<EditorToolbarSection> ToolbarSections { get; set; } = new List<EditorToolbarSection>()
{
public List<EditorToolbarSection> ToolbarSections { get; set; } =
[
new EditorToolbarSection(){ SectionType = EditorToolbarSectionType.Format },
new EditorToolbarSection(){ SectionType = EditorToolbarSectionType.Insert },
new EditorToolbarSection(){ SectionType = EditorToolbarSectionType.Draw },
new EditorToolbarSection(){ SectionType = EditorToolbarSectionType.Options }
};
];
private EditorToolbarSection selectedToolbarSection;
@@ -190,7 +188,7 @@ namespace Wino.Mail.ViewModels
// Save recipients.
SaveAddressInfo(ToItems, CurrentMimeMessage.To);
SaveAddressInfo(CCItemsItems, CurrentMimeMessage.Cc);
SaveAddressInfo(CCItems, CurrentMimeMessage.Cc);
SaveAddressInfo(BCCItems, CurrentMimeMessage.Bcc);
SaveImportance();
@@ -239,12 +237,7 @@ namespace Wino.Mail.ViewModels
{
if (GetHTMLBodyFunction != null)
{
var htmlBody = await GetHTMLBodyFunction();
if (!string.IsNullOrEmpty(htmlBody))
{
bodyBuilder.HtmlBody = Regex.Unescape(htmlBody);
}
bodyBuilder.HtmlBody = await GetHTMLBodyFunction();
}
if (!string.IsNullOrEmpty(bodyBuilder.HtmlBody))
@@ -309,7 +302,7 @@ namespace Wino.Mail.ViewModels
// Check if there is any delivering mail address from protocol launch.
if (_launchProtocolService.MailtoParameters != null)
if (_launchProtocolService.MailToUri != null)
{
// TODO
//var requestedMailContact = await GetAddressInformationAsync(_launchProtocolService.MailtoParameters, ToItems);
@@ -322,7 +315,7 @@ namespace Wino.Mail.ViewModels
// DialogService.InfoBarMessage("Invalid Address", "Address is not a valid e-mail address.", InfoBarMessageType.Warning);
// Clear the address.
_launchProtocolService.MailtoParameters = null;
_launchProtocolService.MailToUri = null;
}
}
@@ -427,15 +420,18 @@ namespace Wino.Mail.ViewModels
// Extract information
ToItems.Clear();
CCItemsItems.Clear();
CCItems.Clear();
BCCItems.Clear();
LoadAddressInfo(replyingMime.To, ToItems);
LoadAddressInfo(replyingMime.Cc, CCItemsItems);
LoadAddressInfo(replyingMime.Cc, CCItems);
LoadAddressInfo(replyingMime.Bcc, BCCItems);
LoadAttachments(replyingMime.Attachments);
if (replyingMime.Cc.Any() || replyingMime.Bcc.Any())
IsCCBCCVisible = true;
Subject = replyingMime.Subject;
CurrentMimeMessage = replyingMime;

View File

@@ -117,7 +117,7 @@ namespace Wino.Mail.ViewModels
#endregion
public INativeAppService NativeAppService { get; }
public IStatePersistanceService StatePersistanceService { get; }
public IStatePersistanceService StatePersistenceService { get; }
public IPreferencesService PreferencesService { get; }
public MailRenderingPageViewModel(IDialogService dialogService,
@@ -127,14 +127,14 @@ namespace Wino.Mail.ViewModels
Core.Domain.Interfaces.IMailService mailService,
IFileService fileService,
IWinoRequestDelegator requestDelegator,
IStatePersistanceService statePersistanceService,
IStatePersistanceService statePersistenceService,
IClipboardService clipboardService,
IUnsubscriptionService unsubscriptionService,
IPreferencesService preferencesService,
IWinoServerConnectionManager winoServerConnectionManager) : base(dialogService)
{
NativeAppService = nativeAppService;
StatePersistanceService = statePersistanceService;
StatePersistenceService = statePersistenceService;
PreferencesService = preferencesService;
_winoServerConnectionManager = winoServerConnectionManager;
_clipboardService = clipboardService;
@@ -255,37 +255,27 @@ namespace Wino.Mail.ViewModels
if (initializedMailItemViewModel == null) return;
// Create new draft.
var draftOptions = new DraftCreationOptions();
if (operation == MailOperation.Reply)
draftOptions.Reason = DraftCreationReason.Reply;
else if (operation == MailOperation.ReplyAll)
draftOptions.Reason = DraftCreationReason.ReplyAll;
else if (operation == MailOperation.Forward)
draftOptions.Reason = DraftCreationReason.Forward;
// TODO: Separate mailto related stuff out of DraftCreationOptions and provide better
// model for draft preperation request. Right now it's a mess.
draftOptions.ReferenceMailCopy = initializedMailItemViewModel.MailCopy;
draftOptions.ReferenceMimeMessage = initializedMimeMessageInformation.MimeMessage;
var createdMimeMessage = await _mailService.CreateDraftMimeBase64Async(initializedMailItemViewModel.AssignedAccount.Id, draftOptions).ConfigureAwait(false);
var createdDraftMailMessage = await _mailService.CreateDraftAsync(initializedMailItemViewModel.AssignedAccount,
createdMimeMessage,
initializedMimeMessageInformation.MimeMessage,
initializedMailItemViewModel).ConfigureAwait(false);
var draftPreperationRequest = new DraftPreperationRequest(initializedMailItemViewModel.AssignedAccount,
createdDraftMailMessage,
createdMimeMessage)
var draftOptions = new DraftCreationOptions()
{
ReferenceMimeMessage = initializedMimeMessageInformation.MimeMessage,
ReferenceMailCopy = initializedMailItemViewModel.MailCopy
Reason = operation switch
{
MailOperation.Reply => DraftCreationReason.Reply,
MailOperation.ReplyAll => DraftCreationReason.ReplyAll,
MailOperation.Forward => DraftCreationReason.Forward,
_ => DraftCreationReason.Empty
},
ReferencedMessage = new ReferencedMessage()
{
MimeMessage = initializedMimeMessageInformation.MimeMessage,
MailCopy = initializedMailItemViewModel.MailCopy
}
};
await _requestDelegator.ExecuteAsync(draftPreperationRequest);
var (draftMailCopy, draftBase64MimeMessage) = await _mailService.CreateDraftAsync(initializedMailItemViewModel.AssignedAccount, draftOptions).ConfigureAwait(false);
var draftPreparationRequest = new DraftPreparationRequest(initializedMailItemViewModel.AssignedAccount, draftMailCopy, draftBase64MimeMessage, initializedMailItemViewModel.MailCopy);
await _requestDelegator.ExecuteAsync(draftPreparationRequest);
}
else if (initializedMailItemViewModel != null)
@@ -453,7 +443,7 @@ namespace Wino.Mail.ViewModels
OnPropertyChanged(nameof(IsImageRenderingDisabled));
StatePersistanceService.IsReadingMail = true;
StatePersistenceService.IsReadingMail = true;
});
}
@@ -477,7 +467,7 @@ namespace Wino.Mail.ViewModels
Attachments.Clear();
MenuItems.Clear();
StatePersistanceService.IsReadingMail = false;
StatePersistenceService.IsReadingMail = false;
}
private void LoadAddressInfo(InternetAddressList list, ObservableCollection<AddressInformation> collection)