Fixing UI thread issues with bulk operations and request queue refactoring.
This commit is contained in:
@@ -14,6 +14,7 @@ using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Messaging.Client.Mails;
|
||||
using Wino.Messaging.UI;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Collections;
|
||||
|
||||
@@ -895,6 +896,121 @@ public class WinoMailCollection : ObservableRecipient, IRecipient<SelectedItemsC
|
||||
return UpdateExistingItemAsync(itemContainer, updatedMailCopy, mailUpdateSource, changedProperties);
|
||||
});
|
||||
|
||||
public Task UpdateMailStateAsync(MailStateChange updatedState, EntityUpdateSource mailUpdateSource)
|
||||
=> RunSerializedAsync(() =>
|
||||
{
|
||||
if (updatedState == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var itemContainer = GetMailItemContainer(updatedState.UniqueId);
|
||||
|
||||
if (itemContainer?.ItemViewModel == null)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
return UpdateExistingMailStateAsync(itemContainer, updatedState, mailUpdateSource);
|
||||
});
|
||||
|
||||
public Task UpdateMailStatesAsync(IEnumerable<MailStateChange> updatedStates, EntityUpdateSource mailUpdateSource)
|
||||
=> RunSerializedAsync(() => UpdateMailStatesInternalAsync(updatedStates, mailUpdateSource));
|
||||
|
||||
public Task UpdateMailCopiesAsync(IEnumerable<MailCopy> updatedMailCopies, EntityUpdateSource mailUpdateSource, MailCopyChangeFlags changedProperties = MailCopyChangeFlags.None)
|
||||
=> RunSerializedAsync(() => UpdateMailCopiesInternalAsync(updatedMailCopies, mailUpdateSource, changedProperties));
|
||||
|
||||
private async Task UpdateExistingMailStateAsync(MailItemContainer itemContainer, MailStateChange updatedState, EntityUpdateSource mailUpdateSource)
|
||||
{
|
||||
if (itemContainer?.ItemViewModel == null || updatedState == null)
|
||||
return;
|
||||
|
||||
var existingItem = itemContainer.ItemViewModel;
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
var appliedChanges = existingItem.ApplyStateChanges(updatedState.IsRead, updatedState.IsFlagged);
|
||||
existingItem.IsBusy = mailUpdateSource == EntityUpdateSource.ClientUpdated;
|
||||
|
||||
if (itemContainer.ThreadViewModel != null && appliedChanges != MailCopyChangeFlags.None)
|
||||
{
|
||||
itemContainer.ThreadViewModel.NotifyMailItemUpdated(existingItem, appliedChanges);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task UpdateMailStatesInternalAsync(IEnumerable<MailStateChange> updatedStates, EntityUpdateSource mailUpdateSource)
|
||||
{
|
||||
var updates = updatedStates?
|
||||
.Where(x => x != null)
|
||||
.GroupBy(x => x.UniqueId)
|
||||
.Select(group =>
|
||||
{
|
||||
var updatedState = group.Last();
|
||||
return new
|
||||
{
|
||||
UpdatedState = updatedState,
|
||||
ItemContainer = GetMailItemContainer(updatedState.UniqueId)
|
||||
};
|
||||
})
|
||||
.Where(x => x.ItemContainer?.ItemViewModel != null)
|
||||
.ToList() ?? [];
|
||||
|
||||
if (updates.Count == 0)
|
||||
return;
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
foreach (var update in updates)
|
||||
{
|
||||
var existingItem = update.ItemContainer.ItemViewModel;
|
||||
var appliedChanges = existingItem.ApplyStateChanges(update.UpdatedState.IsRead, update.UpdatedState.IsFlagged);
|
||||
existingItem.IsBusy = mailUpdateSource == EntityUpdateSource.ClientUpdated;
|
||||
|
||||
if (update.ItemContainer.ThreadViewModel != null && appliedChanges != MailCopyChangeFlags.None)
|
||||
{
|
||||
update.ItemContainer.ThreadViewModel.NotifyMailItemUpdated(existingItem, appliedChanges);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task UpdateMailCopiesInternalAsync(IEnumerable<MailCopy> updatedMailCopies, EntityUpdateSource mailUpdateSource, MailCopyChangeFlags changedProperties)
|
||||
{
|
||||
var updates = updatedMailCopies?
|
||||
.Where(x => x != null)
|
||||
.GroupBy(x => x.UniqueId)
|
||||
.Select(group =>
|
||||
{
|
||||
var updatedMail = group.First();
|
||||
return new
|
||||
{
|
||||
UpdatedMail = updatedMail,
|
||||
ItemContainer = GetMailItemContainer(updatedMail.UniqueId)
|
||||
};
|
||||
})
|
||||
.Where(x => x.ItemContainer?.ItemViewModel != null)
|
||||
.ToList() ?? [];
|
||||
|
||||
if (updates.Count == 0)
|
||||
return;
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
foreach (var update in updates)
|
||||
{
|
||||
var updatedMail = update.UpdatedMail;
|
||||
var itemContainer = update.ItemContainer;
|
||||
var existingItem = itemContainer.ItemViewModel;
|
||||
var appliedChanges = existingItem.UpdateFrom(updatedMail, changedProperties);
|
||||
existingItem.IsBusy = mailUpdateSource == EntityUpdateSource.ClientUpdated;
|
||||
|
||||
if (itemContainer.ThreadViewModel != null && appliedChanges != MailCopyChangeFlags.None)
|
||||
{
|
||||
itemContainer.ThreadViewModel.NotifyMailItemUpdated(existingItem, appliedChanges);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public MailItemViewModel GetFirst() => AllItems.ElementAtOrDefault(0);
|
||||
|
||||
public MailItemViewModel GetNextItem(MailCopy mailCopy)
|
||||
@@ -963,7 +1079,32 @@ public class WinoMailCollection : ObservableRecipient, IRecipient<SelectedItemsC
|
||||
public Task RemoveAsync(MailCopy removeItem)
|
||||
=> RunSerializedAsync(() => RemoveInternalAsync(removeItem));
|
||||
|
||||
public Task RemoveRangeAsync(IEnumerable<MailCopy> removeItems)
|
||||
=> RunSerializedAsync(() => RemoveRangeInternalAsync(removeItems));
|
||||
|
||||
private async Task RemoveInternalAsync(MailCopy removeItem)
|
||||
=> await RemoveInternalAsync(removeItem, notifySelectionChanges: true);
|
||||
|
||||
private async Task RemoveRangeInternalAsync(IEnumerable<MailCopy> removeItems)
|
||||
{
|
||||
var distinctItems = removeItems?
|
||||
.Where(x => x != null)
|
||||
.GroupBy(x => x.UniqueId)
|
||||
.Select(group => group.First())
|
||||
.ToList() ?? [];
|
||||
|
||||
if (distinctItems.Count == 0)
|
||||
return;
|
||||
|
||||
foreach (var removeItem in distinctItems)
|
||||
{
|
||||
await RemoveInternalAsync(removeItem, notifySelectionChanges: false);
|
||||
}
|
||||
|
||||
await NotifySelectionChangesAsync();
|
||||
}
|
||||
|
||||
private async Task RemoveInternalAsync(MailCopy removeItem, bool notifySelectionChanges)
|
||||
{
|
||||
var itemContainer = GetMailItemContainer(removeItem.UniqueId);
|
||||
|
||||
@@ -1030,7 +1171,10 @@ public class WinoMailCollection : ObservableRecipient, IRecipient<SelectedItemsC
|
||||
}
|
||||
}
|
||||
|
||||
await NotifySelectionChangesAsync();
|
||||
if (notifySelectionChanges)
|
||||
{
|
||||
await NotifySelectionChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<IMailListItem> AllItemsIncludingThreads
|
||||
@@ -1207,4 +1351,5 @@ public class WinoMailCollection : ObservableRecipient, IRecipient<SelectedItemsC
|
||||
ItemSelectionChanged?.Invoke(this, null);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user