Fixing outlook attachments, re-using compose page and some additional fixes on the mime headers for outlook.
This commit is contained in:
@@ -21,11 +21,13 @@ using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Extensions;
|
||||
using Wino.Core.Services;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Mail.ViewModels.Messages;
|
||||
using Wino.Messaging.Client.Mails;
|
||||
|
||||
namespace Wino.Mail.ViewModels;
|
||||
|
||||
public partial class ComposePageViewModel : MailBaseViewModel
|
||||
public partial class ComposePageViewModel : MailBaseViewModel,
|
||||
IRecipient<NewComposeDraftItemRequestedEvent>
|
||||
{
|
||||
public Func<Task<string>> GetHTMLBodyFunction;
|
||||
|
||||
@@ -432,6 +434,35 @@ public partial class ComposePageViewModel : MailBaseViewModel
|
||||
}
|
||||
}
|
||||
|
||||
public async void Receive(NewComposeDraftItemRequestedEvent message)
|
||||
{
|
||||
// Save current draft before switching.
|
||||
await UpdateMimeChangesAsync();
|
||||
|
||||
// Reset state for the new draft.
|
||||
isUpdatingMimeBlocked = false;
|
||||
ComposingAccount = null;
|
||||
IncludedAttachments.Clear();
|
||||
|
||||
// Set the new draft item and prepare it.
|
||||
CurrentMailDraftItem = message.MailItemViewModel;
|
||||
await TryPrepareComposeAsync(true);
|
||||
}
|
||||
|
||||
protected override void RegisterRecipients()
|
||||
{
|
||||
base.RegisterRecipients();
|
||||
|
||||
Messenger.Register<NewComposeDraftItemRequestedEvent>(this);
|
||||
}
|
||||
|
||||
protected override void UnregisterRecipients()
|
||||
{
|
||||
base.UnregisterRecipients();
|
||||
|
||||
Messenger.Unregister<NewComposeDraftItemRequestedEvent>(this);
|
||||
}
|
||||
|
||||
private async Task<bool> InitializeComposerAccountAsync()
|
||||
{
|
||||
if (CurrentMailDraftItem == null) return false;
|
||||
@@ -550,6 +581,8 @@ public partial class ComposePageViewModel : MailBaseViewModel
|
||||
{
|
||||
if (CurrentMimeMessage == null) return;
|
||||
|
||||
IncludedAttachments.Clear();
|
||||
|
||||
foreach (var attachment in CurrentMimeMessage.Attachments)
|
||||
{
|
||||
if (attachment.IsAttachment && attachment is MimePart attachmentPart)
|
||||
|
||||
@@ -635,6 +635,56 @@ public partial class MailListPageViewModel : MailBaseViewModel,
|
||||
|
||||
if (isFromDraftOrSentFolder)
|
||||
{
|
||||
// Fix for draft duplication: When a draft is created for reply/forward, it's first added as local draft.
|
||||
// Then the server sync fetches it back. We should skip adding remote drafts if a local draft already exists
|
||||
// with the same ThreadId. The mapping system (DraftMapped) will handle updating the existing local draft.
|
||||
if (addedMail.IsDraft && !addedMail.IsLocalDraft && !string.IsNullOrEmpty(addedMail.ThreadId))
|
||||
{
|
||||
// Check if collection already has a local draft with the same ThreadId in the same folder
|
||||
bool hasLocalDraftInSameThread = false;
|
||||
|
||||
foreach (var group in MailCollection.MailItems)
|
||||
{
|
||||
foreach (var item in group)
|
||||
{
|
||||
if (item is MailItemViewModel mailItem)
|
||||
{
|
||||
if (mailItem.IsDraft &&
|
||||
mailItem.MailCopy.IsLocalDraft &&
|
||||
mailItem.MailCopy.ThreadId == addedMail.ThreadId &&
|
||||
mailItem.MailCopy.FolderId == addedMail.FolderId)
|
||||
{
|
||||
hasLocalDraftInSameThread = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (item is ThreadMailItemViewModel threadItem)
|
||||
{
|
||||
foreach (var threadEmail in threadItem.ThreadEmails)
|
||||
{
|
||||
if (threadEmail.IsDraft &&
|
||||
threadEmail.MailCopy.IsLocalDraft &&
|
||||
threadEmail.MailCopy.ThreadId == addedMail.ThreadId &&
|
||||
threadEmail.MailCopy.FolderId == addedMail.FolderId)
|
||||
{
|
||||
hasLocalDraftInSameThread = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasLocalDraftInSameThread) break;
|
||||
}
|
||||
}
|
||||
if (hasLocalDraftInSameThread) break;
|
||||
}
|
||||
|
||||
if (hasLocalDraftInSameThread)
|
||||
{
|
||||
// Local draft exists in the same thread - skip adding remote duplicate
|
||||
// The mapping system will update the local draft with remote IDs when DraftMapped message is received
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Only add if the ThreadId exists in the collection (can be threaded with existing items)
|
||||
if (!ThreadIdExistsInCollection(addedMail)) return;
|
||||
}
|
||||
@@ -757,6 +807,17 @@ public partial class MailListPageViewModel : MailBaseViewModel,
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDraftMapped(string localDraftCopyId, string remoteDraftCopyId)
|
||||
{
|
||||
base.OnDraftMapped(localDraftCopyId, remoteDraftCopyId);
|
||||
|
||||
// When a draft is mapped from local to remote, the database has been updated
|
||||
// but the UI collection still references the MailCopy object with old IDs.
|
||||
// The MailCollection.AddAsync method checks UniqueId (which doesn't change during mapping)
|
||||
// so if mapping worked correctly, no duplicate should appear.
|
||||
// This method is here for future enhancements if additional UI updates are needed.
|
||||
}
|
||||
|
||||
private async Task<List<MailItemViewModel>> PrepareMailViewModelsAsync(IEnumerable<MailCopy> mailItems, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Run ViewModel creation on background thread to avoid blocking UI
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// When the compose page is already active, but a different draft item is selected.
|
||||
/// To not trigger navigation again and re-use existing WebView2 editor.
|
||||
/// </summary>
|
||||
/// <param name="MailItemViewModel">The new draft mail item to compose.</param>
|
||||
public record NewComposeDraftItemRequestedEvent(MailItemViewModel MailItemViewModel);
|
||||
Reference in New Issue
Block a user