Info panel for synchronizers in shell.

This commit is contained in:
Burak Kaan Köse
2026-02-07 14:03:41 +01:00
parent d28de50ec6
commit 331b966556
9 changed files with 314 additions and 12 deletions
@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Wino.Core.Domain;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Requests.Folder;
using Wino.Core.Requests.Mail;
namespace Wino.Core.Helpers;
/// <summary>
/// Converts queued synchronization requests into user-facing action descriptions.
/// </summary>
public static class SynchronizationActionHelper
{
public static List<SynchronizationActionItem> CreateActionItems(
IEnumerable<IRequestBase> requests, Guid accountId, string accountName)
{
var items = new List<SynchronizationActionItem>();
// Group mail action requests by operation
var mailRequests = requests.OfType<IMailActionRequest>();
var mailGroups = mailRequests.GroupBy(r => GetMailActionKey(r));
foreach (var group in mailGroups)
{
var description = GetMailActionDescription(group.Key, group.ToList());
if (description != null)
{
items.Add(new SynchronizationActionItem
{
AccountId = accountId,
AccountName = accountName,
Description = description
});
}
}
// Handle folder action requests individually
var folderRequests = requests.OfType<IFolderActionRequest>();
foreach (var folderRequest in folderRequests)
{
var description = GetFolderActionDescription(folderRequest);
if (description != null)
{
items.Add(new SynchronizationActionItem
{
AccountId = accountId,
AccountName = accountName,
Description = description
});
}
}
return items;
}
/// <summary>
/// Returns a key that differentiates MarkRead vs MarkUnread, Flag vs Unflag, Archive vs Unarchive.
/// </summary>
private static string GetMailActionKey(IMailActionRequest request)
{
return request switch
{
MarkReadRequest r => r.IsRead ? "MarkRead" : "MarkUnread",
ChangeFlagRequest r => r.IsFlagged ? "SetFlag" : "ClearFlag",
ArchiveRequest r => r.IsArchiving ? "Archive" : "Unarchive",
_ => request.Operation.ToString()
};
}
private static string GetMailActionDescription(string actionKey, List<IMailActionRequest> requests)
{
int count = requests.Count;
return actionKey switch
{
"MarkRead" => string.Format(Translator.SyncAction_MarkingAsRead, count),
"MarkUnread" => string.Format(Translator.SyncAction_MarkingAsUnread, count),
"Delete" => string.Format(Translator.SyncAction_Deleting, count),
"Move" => string.Format(Translator.SyncAction_Moving, count),
"Archive" => string.Format(Translator.SyncAction_Archiving, count),
"Unarchive" => string.Format(Translator.SyncAction_Unarchiving, count),
"SetFlag" => string.Format(Translator.SyncAction_SettingFlag, count),
"ClearFlag" => string.Format(Translator.SyncAction_ClearingFlag, count),
"CreateDraft" => Translator.SyncAction_CreatingDraft,
"Send" => Translator.SyncAction_SendingMail,
"MoveToFocused" => string.Format(Translator.SyncAction_MovingToFocused, count),
"AlwaysMoveTo" => string.Format(Translator.SyncAction_Moving, count),
_ => null
};
}
private static string GetFolderActionDescription(IFolderActionRequest request)
{
return request switch
{
RenameFolderRequest => Translator.SyncAction_RenamingFolder,
EmptyFolderRequest => Translator.SyncAction_EmptyingFolder,
MarkFolderAsReadRequest => Translator.SyncAction_MarkingFolderAsRead,
_ => null
};
}
}
+39 -9
View File
@@ -13,9 +13,11 @@ using Wino.Core.Domain.Models.Calendar;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Helpers;
using Wino.Core.Requests.Calendar;
using Wino.Core.Requests.Mail;
using Wino.Messaging.Server;
using Wino.Messaging.UI;
namespace Wino.Core.Services;
@@ -24,14 +26,17 @@ public class WinoRequestDelegator : IWinoRequestDelegator
private readonly IWinoRequestProcessor _winoRequestProcessor;
private readonly IFolderService _folderService;
private readonly IMailDialogService _dialogService;
private readonly IAccountService _accountService;
public WinoRequestDelegator(IWinoRequestProcessor winoRequestProcessor,
IFolderService folderService,
IMailDialogService dialogService)
IMailDialogService dialogService,
IAccountService accountService)
{
_winoRequestProcessor = winoRequestProcessor;
_folderService = folderService;
_dialogService = dialogService;
_accountService = accountService;
}
public async Task ExecuteAsync(MailOperationPreperationRequest request)
@@ -82,14 +87,20 @@ public class WinoRequestDelegator : IWinoRequestDelegator
var accountIds = requests.GroupBy(a => a.Item.AssignedAccount.Id);
// Queue requests for each account and start synchronization.
foreach (var accountId in accountIds)
foreach (var accountGroup in accountIds)
{
foreach (var accountRequest in accountId)
foreach (var accountRequest in accountGroup)
{
await QueueRequestAsync(accountRequest, accountId.Key);
await QueueRequestAsync(accountRequest, accountGroup.Key);
}
await QueueSynchronizationAsync(accountId.Key);
var account = accountGroup.First().Item.AssignedAccount;
var actionItems = SynchronizationActionHelper.CreateActionItems(accountGroup, accountGroup.Key, account.Name);
if (actionItems.Count > 0)
WeakReferenceMessenger.Default.Send(new SynchronizationActionsAdded(accountGroup.Key, account.Name, actionItems));
await QueueSynchronizationAsync(accountGroup.Key);
}
}
@@ -117,23 +128,28 @@ public class WinoRequestDelegator : IWinoRequestDelegator
if (request == null) return;
await QueueRequestAsync(request, accountId);
await SendSyncActionsAddedAsync([request], accountId);
await QueueSynchronizationAsync(accountId);
}
public async Task ExecuteAsync(DraftPreparationRequest draftPreperationRequest)
{
var request = new CreateDraftRequest(draftPreperationRequest);
var accountId = draftPreperationRequest.Account.Id;
await QueueRequestAsync(request, draftPreperationRequest.Account.Id);
await QueueSynchronizationAsync(draftPreperationRequest.Account.Id);
await QueueRequestAsync(request, accountId);
await SendSyncActionsAddedAsync([request], accountId, draftPreperationRequest.Account.Name);
await QueueSynchronizationAsync(accountId);
}
public async Task ExecuteAsync(SendDraftPreparationRequest sendDraftPreperationRequest)
{
var request = new SendDraftRequest(sendDraftPreperationRequest);
var account = sendDraftPreperationRequest.MailItem.AssignedAccount;
await QueueRequestAsync(request, sendDraftPreperationRequest.MailItem.AssignedAccount.Id);
await QueueSynchronizationAsync(sendDraftPreperationRequest.MailItem.AssignedAccount.Id);
await QueueRequestAsync(request, account.Id);
await SendSyncActionsAddedAsync([request], account.Id, account.Name);
await QueueSynchronizationAsync(account.Id);
}
public async Task ExecuteAsync(CalendarOperationPreparationRequest calendarPreparationRequest)
@@ -187,6 +203,20 @@ public class WinoRequestDelegator : IWinoRequestDelegator
return Task.CompletedTask;
}
private async Task SendSyncActionsAddedAsync(IEnumerable<IRequestBase> requests, Guid accountId, string accountName = null)
{
if (accountName == null)
{
var account = await _accountService.GetAccountAsync(accountId);
accountName = account?.Name ?? string.Empty;
}
var actionItems = SynchronizationActionHelper.CreateActionItems(requests, accountId, accountName);
if (actionItems.Count > 0)
WeakReferenceMessenger.Default.Send(new SynchronizationActionsAdded(accountId, accountName, actionItems));
}
private Task QueueCalendarSynchronizationAsync(Guid accountId)
{
var options = new CalendarSynchronizationOptions()
@@ -215,6 +215,8 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
await ExecuteNativeRequestsAsync(nativeRequests, activeSynchronizationCancellationToken).ConfigureAwait(false);
Messenger.Send(new SynchronizationActionsCompleted(Account.Id));
PublishUnreadItemChanges();
// Execute request sync options should be re-calculated after execution.
@@ -399,6 +401,8 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
await ExecuteNativeRequestsAsync(nativeRequests, cancellationToken).ConfigureAwait(false);
Messenger.Send(new SynchronizationActionsCompleted(Account.Id));
// Let servers to finish their job. Sometimes the servers don't respond immediately.
shouldDelayExecution = requestCopies.Any(a => a.ResynchronizationDelay > 0);