Some experiments.
This commit is contained in:
@@ -1309,6 +1309,14 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
||||
public override async Task ExecuteNativeRequestsAsync(List<IRequestBundle<IClientServiceRequest>> batchedRequests,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// First apply all UI changes immediately before any batching.
|
||||
// This ensures UI reflects changes right away, regardless of batch processing.
|
||||
foreach (var bundle in batchedRequests)
|
||||
{
|
||||
bundle.UIChangeRequest?.ApplyUIChanges();
|
||||
}
|
||||
|
||||
// Now batch and execute the network requests.
|
||||
var batchedBundles = batchedRequests.Batch((int)MaximumAllowedBatchRequestSize);
|
||||
var bundleCount = batchedBundles.Count();
|
||||
|
||||
@@ -1325,7 +1333,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
||||
for (int k = 0; k < bundleRequestCount; k++)
|
||||
{
|
||||
var requestBundle = bundle.ElementAt(k);
|
||||
requestBundle.UIChangeRequest?.ApplyUIChanges();
|
||||
// UI changes are already applied above before batching.
|
||||
|
||||
nativeBatchRequest.Queue<object>(requestBundle.NativeRequest, (content, error, index, message)
|
||||
=> bundleTasks.Add(ProcessSingleNativeRequestResponseAsync(requestBundle, error, message, cancellationToken)));
|
||||
|
||||
@@ -1506,6 +1506,14 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
||||
|
||||
public override async Task ExecuteNativeRequestsAsync(List<IRequestBundle<RequestInformation>> batchedRequests, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// First apply all UI changes immediately before any batching.
|
||||
// This ensures UI reflects changes right away, regardless of batch processing.
|
||||
foreach (var bundle in batchedRequests)
|
||||
{
|
||||
bundle.UIChangeRequest?.ApplyUIChanges();
|
||||
}
|
||||
|
||||
// Now batch and execute the network requests.
|
||||
var batchedGroups = batchedRequests.Batch((int)MaximumAllowedBatchRequestSize);
|
||||
|
||||
foreach (var batch in batchedGroups)
|
||||
@@ -1542,7 +1550,7 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
||||
var bundle = batch.ElementAt(i);
|
||||
requiresSerial |= bundle.UIChangeRequest is SendDraftRequest;
|
||||
|
||||
bundle.UIChangeRequest?.ApplyUIChanges();
|
||||
// UI changes are already applied in ExecuteNativeRequestsAsync before batching.
|
||||
var batchRequestId = await batchContent.AddBatchRequestStepAsync(bundle.NativeRequest);
|
||||
bundle.BundleId = batchRequestId;
|
||||
bundleIdMap[batchRequestId] = bundle;
|
||||
|
||||
@@ -444,7 +444,7 @@ public class WinoMailCollection : ObservableRecipient, IRecipient<SelectedItemsC
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
existingItem.MailCopy = updatedItem;
|
||||
existingItem.UpdateFrom(updatedItem);
|
||||
});
|
||||
|
||||
UpdateUniqueIdHashes(existingItem, true);
|
||||
@@ -574,7 +574,7 @@ public class WinoMailCollection : ObservableRecipient, IRecipient<SelectedItemsC
|
||||
foreach (var (existing, updated) in itemsToUpdate)
|
||||
{
|
||||
UpdateUniqueIdHashes(existing, false);
|
||||
existing.MailCopy = updated;
|
||||
existing.UpdateFrom(updated);
|
||||
UpdateUniqueIdHashes(existing, true);
|
||||
}
|
||||
});
|
||||
@@ -720,7 +720,7 @@ public class WinoMailCollection : ObservableRecipient, IRecipient<SelectedItemsC
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fins the item container that updated mail copy belongs to and updates it.
|
||||
/// Finds the item container that updated mail copy belongs to and updates it.
|
||||
/// </summary>
|
||||
/// <param name="updatedMailCopy">Updated mail copy.</param>
|
||||
/// <returns></returns>
|
||||
@@ -739,8 +739,9 @@ public class WinoMailCollection : ObservableRecipient, IRecipient<SelectedItemsC
|
||||
{
|
||||
UpdateUniqueIdHashes(itemContainer.ItemViewModel, false);
|
||||
|
||||
// Update the MailCopy - this will automatically notify all dependent properties
|
||||
itemContainer.ItemViewModel.MailCopy = updatedMailCopy;
|
||||
// Update the MailCopy using UpdateFrom to properly notify all XAML bindings
|
||||
// This maintains reference integrity and ensures PropertyChanged is raised for all properties
|
||||
itemContainer.ItemViewModel.UpdateFrom(updatedMailCopy);
|
||||
|
||||
UpdateUniqueIdHashes(itemContainer.ItemViewModel, true);
|
||||
}
|
||||
@@ -748,7 +749,7 @@ public class WinoMailCollection : ObservableRecipient, IRecipient<SelectedItemsC
|
||||
// Trigger thread property notifications if this item is in a thread
|
||||
if (itemContainer.ThreadViewModel != null)
|
||||
{
|
||||
itemContainer.ThreadViewModel.ThreadEmails = itemContainer.ThreadViewModel.ThreadEmails;
|
||||
itemContainer.ThreadViewModel.NotifyMailItemUpdated(itemContainer.ItemViewModel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -643,7 +643,7 @@ public partial class ComposePageViewModel : MailBaseViewModel
|
||||
{
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
CurrentMailDraftItem.MailCopy = updatedMail;
|
||||
CurrentMailDraftItem.UpdateFrom(updatedMail);
|
||||
DiscardCommand.NotifyCanExecuteChanged();
|
||||
SendCommand.NotifyCanExecuteChanged();
|
||||
});
|
||||
|
||||
@@ -184,4 +184,67 @@ public partial class MailItemViewModel(MailCopy mailCopy) : ObservableRecipient,
|
||||
yield return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the MailCopy with new data and notifies all bound properties.
|
||||
/// This method copies values from the source to the existing MailCopy to maintain reference integrity,
|
||||
/// then explicitly raises PropertyChanged for all dependent properties.
|
||||
/// </summary>
|
||||
/// <param name="source">The source MailCopy with updated values.</param>
|
||||
public void UpdateFrom(MailCopy source)
|
||||
{
|
||||
if (source == null) return;
|
||||
|
||||
// Update the underlying MailCopy properties directly to maintain reference integrity
|
||||
// This is important because other parts of the app may hold references to this MailCopy
|
||||
// Note: UniqueId is the primary key and should match - we don't update it
|
||||
MailCopy.Id = source.Id;
|
||||
MailCopy.FolderId = source.FolderId;
|
||||
MailCopy.ThreadId = source.ThreadId;
|
||||
MailCopy.MessageId = source.MessageId;
|
||||
MailCopy.References = source.References;
|
||||
MailCopy.InReplyTo = source.InReplyTo;
|
||||
MailCopy.IsDraft = source.IsDraft;
|
||||
MailCopy.DraftId = source.DraftId;
|
||||
MailCopy.CreationDate = source.CreationDate;
|
||||
MailCopy.Subject = source.Subject;
|
||||
MailCopy.PreviewText = source.PreviewText;
|
||||
MailCopy.FromName = source.FromName;
|
||||
MailCopy.FromAddress = source.FromAddress;
|
||||
MailCopy.HasAttachments = source.HasAttachments;
|
||||
MailCopy.Importance = source.Importance;
|
||||
MailCopy.IsRead = source.IsRead;
|
||||
MailCopy.IsFlagged = source.IsFlagged;
|
||||
MailCopy.IsFocused = source.IsFocused;
|
||||
MailCopy.FileId = source.FileId;
|
||||
MailCopy.ItemType = source.ItemType;
|
||||
MailCopy.SenderContact = source.SenderContact;
|
||||
MailCopy.AssignedAccount = source.AssignedAccount;
|
||||
MailCopy.AssignedFolder = source.AssignedFolder;
|
||||
|
||||
// Raise PropertyChanged for all properties that XAML may bind to
|
||||
OnPropertyChanged(nameof(CreationDate));
|
||||
OnPropertyChanged(nameof(IsFlagged));
|
||||
OnPropertyChanged(nameof(FromName));
|
||||
OnPropertyChanged(nameof(IsFocused));
|
||||
OnPropertyChanged(nameof(IsRead));
|
||||
OnPropertyChanged(nameof(IsDraft));
|
||||
OnPropertyChanged(nameof(DraftId));
|
||||
OnPropertyChanged(nameof(Id));
|
||||
OnPropertyChanged(nameof(Subject));
|
||||
OnPropertyChanged(nameof(PreviewText));
|
||||
OnPropertyChanged(nameof(FromAddress));
|
||||
OnPropertyChanged(nameof(HasAttachments));
|
||||
OnPropertyChanged(nameof(Importance));
|
||||
OnPropertyChanged(nameof(ThreadId));
|
||||
OnPropertyChanged(nameof(MessageId));
|
||||
OnPropertyChanged(nameof(References));
|
||||
OnPropertyChanged(nameof(InReplyTo));
|
||||
OnPropertyChanged(nameof(FileId));
|
||||
OnPropertyChanged(nameof(FolderId));
|
||||
OnPropertyChanged(nameof(UniqueId));
|
||||
OnPropertyChanged(nameof(Base64ContactPicture));
|
||||
OnPropertyChanged(nameof(SortingDate));
|
||||
OnPropertyChanged(nameof(SortingName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +213,40 @@ public partial class ThreadMailItemViewModel : ObservableRecipient, IMailListIte
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notifies that a mail item within this thread has been updated.
|
||||
/// This raises PropertyChanged for all thread-level computed properties that depend on child items.
|
||||
/// </summary>
|
||||
/// <param name="updatedMailItem">The mail item that was updated (can be null to refresh all).</param>
|
||||
public void NotifyMailItemUpdated(MailItemViewModel updatedMailItem)
|
||||
{
|
||||
// Raise PropertyChanged for all computed properties that depend on ThreadEmails contents
|
||||
OnPropertyChanged(nameof(Subject));
|
||||
OnPropertyChanged(nameof(FromName));
|
||||
OnPropertyChanged(nameof(CreationDate));
|
||||
OnPropertyChanged(nameof(FromAddress));
|
||||
OnPropertyChanged(nameof(PreviewText));
|
||||
OnPropertyChanged(nameof(HasAttachments));
|
||||
OnPropertyChanged(nameof(IsFlagged));
|
||||
OnPropertyChanged(nameof(IsFocused));
|
||||
OnPropertyChanged(nameof(IsRead));
|
||||
OnPropertyChanged(nameof(IsDraft));
|
||||
OnPropertyChanged(nameof(DraftId));
|
||||
OnPropertyChanged(nameof(Id));
|
||||
OnPropertyChanged(nameof(Importance));
|
||||
OnPropertyChanged(nameof(ThreadId));
|
||||
OnPropertyChanged(nameof(MessageId));
|
||||
OnPropertyChanged(nameof(References));
|
||||
OnPropertyChanged(nameof(InReplyTo));
|
||||
OnPropertyChanged(nameof(FileId));
|
||||
OnPropertyChanged(nameof(FolderId));
|
||||
OnPropertyChanged(nameof(UniqueId));
|
||||
OnPropertyChanged(nameof(Base64ContactPicture));
|
||||
OnPropertyChanged(nameof(ThumbnailUpdatedEvent));
|
||||
OnPropertyChanged(nameof(SortingDate));
|
||||
OnPropertyChanged(nameof(SortingName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this thread contains an email with the specified unique ID
|
||||
/// </summary>
|
||||
|
||||
@@ -668,8 +668,6 @@ public partial class MailListPageViewModel : MailBaseViewModel,
|
||||
{
|
||||
base.OnMailUpdated(updatedMail);
|
||||
|
||||
Debug.WriteLine($"Updating {updatedMail.Id}-> {updatedMail.UniqueId}");
|
||||
|
||||
await MailCollection.UpdateMailCopy(updatedMail);
|
||||
|
||||
await ExecuteUIThread(() => { SetupTopBarActions(); });
|
||||
|
||||
Reference in New Issue
Block a user