diff --git a/Wino.Calendar.ViewModels/CalendarPageViewModel.cs b/Wino.Calendar.ViewModels/CalendarPageViewModel.cs
index 7552de6e..e391b957 100644
--- a/Wino.Calendar.ViewModels/CalendarPageViewModel.cs
+++ b/Wino.Calendar.ViewModels/CalendarPageViewModel.cs
@@ -11,6 +11,7 @@ using Wino.Calendar.Models.CalendarTypeStrategies;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Calendar;
+using Wino.Core.Domain.Models.Calendar.CalendarTypeStrategies;
using Wino.Core.Domain.Models.Navigation;
using Wino.Core.MenuItems;
using Wino.Core.ViewModels;
diff --git a/Wino.Core.Domain/Enums/MailOperation.cs b/Wino.Core.Domain/Enums/MailOperation.cs
index 0d9962cd..b2149b22 100644
--- a/Wino.Core.Domain/Enums/MailOperation.cs
+++ b/Wino.Core.Domain/Enums/MailOperation.cs
@@ -12,6 +12,10 @@
AlwaysMoveTo,
MoveToFocused,
Archive,
+ }
+
+ public enum FolderSynchronizerOperation
+ {
RenameFolder,
EmptyFolder,
MarkFolderRead,
diff --git a/Wino.Core.Domain/Interfaces/IRequestBundle.cs b/Wino.Core.Domain/Interfaces/IRequestBundle.cs
index b573d4f3..018bae3f 100644
--- a/Wino.Core.Domain/Interfaces/IRequestBundle.cs
+++ b/Wino.Core.Domain/Interfaces/IRequestBundle.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using Wino.Core.Domain.Entities.Mail;
+using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Interfaces
@@ -10,7 +9,7 @@ namespace Wino.Core.Domain.Interfaces
public interface IRequestBundle
{
string BundleId { get; set; }
- IRequestBase Request { get; }
+ IUIChangeRequest UIChangeRequest { get; }
}
///
@@ -20,15 +19,25 @@ namespace Wino.Core.Domain.Interfaces
public interface IRequestBundle : IRequestBundle
{
TRequest NativeRequest { get; }
+ IRequestBase Request { get; }
}
- public interface IRequestBase : IClientMessage
+ public interface IRequestBase : IClientMessage, IUIChangeRequest
{
///
- /// Synchronizer option to perform.
+ /// Whether synchronizations should be delayed after executing this request.
+ /// Specially Outlook sometimes don't report changes back immidiately after sending the API request.
+ /// This results following synchronization to miss the changes.
+ /// We add small delay for the following synchronization after executing current requests to overcome this issue.
+ /// Default is false.
///
- MailSynchronizerOperation Operation { get; }
+ int ResynchronizationDelay { get; }
+ object GroupingKey();
+ }
+
+ public interface IUIChangeRequest
+ {
///
/// UI changes to apply to the item before sending the request to the server.
/// Changes here only affect the UI, not the item itself.
@@ -40,30 +49,18 @@ namespace Wino.Core.Domain.Interfaces
/// Reverts the UI changes applied by if the request fails.
///
void RevertUIChanges();
-
- ///
- /// Whether synchronizations should be delayed after executing this request.
- /// Specially Outlook sometimes don't report changes back immidiately after sending the API request.
- /// This results following synchronization to miss the changes.
- /// We add small delay for the following synchronization after executing current requests to overcome this issue.
- /// Default is false.
- ///
- int ResynchronizationDelay { get; }
}
- public interface IRequest : IRequestBase
+ public interface IMailActionRequest : IRequestBase
{
MailCopy Item { get; }
- IBatchChangeRequest CreateBatch(IEnumerable requests);
+ MailSynchronizerOperation Operation { get; }
}
- public interface IFolderRequest : IRequestBase
+ public interface IFolderActionRequest : IRequestBase
{
MailItemFolder Folder { get; }
- }
- public interface IBatchChangeRequest : IRequestBase
- {
- IEnumerable Items { get; }
+ FolderSynchronizerOperation Operation { get; }
}
}
diff --git a/Wino.Core.Domain/Interfaces/IWinoRequestProcessor.cs b/Wino.Core.Domain/Interfaces/IWinoRequestProcessor.cs
index 32b1aacf..26cfb574 100644
--- a/Wino.Core.Domain/Interfaces/IWinoRequestProcessor.cs
+++ b/Wino.Core.Domain/Interfaces/IWinoRequestProcessor.cs
@@ -12,7 +12,7 @@ namespace Wino.Core.Domain.Interfaces
///
///
/// Base request that synchronizer can execute.
- Task PrepareFolderRequestAsync(FolderOperationPreperationRequest request);
+ Task PrepareFolderRequestAsync(FolderOperationPreperationRequest request);
///
/// Prepares proper Wino requests for synchronizers to execute categorized by AccountId and FolderId.
@@ -21,6 +21,6 @@ namespace Wino.Core.Domain.Interfaces
/// Selected mails.
/// When required folder target is not available for account.
/// Base request that synchronizer can execute.
- Task> PrepareRequestsAsync(MailOperationPreperationRequest request);
+ Task> PrepareRequestsAsync(MailOperationPreperationRequest request);
}
}
diff --git a/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/BaseCalendarTypeDrawingStrategy.cs b/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/BaseCalendarTypeDrawingStrategy.cs
index f5edf4c6..bfb164ba 100644
--- a/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/BaseCalendarTypeDrawingStrategy.cs
+++ b/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/BaseCalendarTypeDrawingStrategy.cs
@@ -2,7 +2,7 @@
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Calendar;
-namespace Wino.Calendar.Models.CalendarTypeStrategies
+namespace Wino.Core.Domain.Models.Calendar.CalendarTypeStrategies
{
public abstract class BaseCalendarTypeDrawingStrategy
{
diff --git a/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/DayCalendarDrawingStrategy.cs b/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/DayCalendarDrawingStrategy.cs
index 931edad6..4b2a3256 100644
--- a/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/DayCalendarDrawingStrategy.cs
+++ b/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/DayCalendarDrawingStrategy.cs
@@ -2,7 +2,7 @@
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Calendar;
-namespace Wino.Calendar.Models.CalendarTypeStrategies
+namespace Wino.Core.Domain.Models.Calendar.CalendarTypeStrategies
{
public class DayCalendarDrawingStrategy : BaseCalendarTypeDrawingStrategy
{
diff --git a/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/WeekCalendarDrawingStrategy.cs b/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/WeekCalendarDrawingStrategy.cs
index bd83eafd..7a1c108d 100644
--- a/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/WeekCalendarDrawingStrategy.cs
+++ b/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/WeekCalendarDrawingStrategy.cs
@@ -1,11 +1,11 @@
using System;
using Wino.Core.Domain.Models.Calendar;
-namespace Wino.Calendar.Models.CalendarTypeStrategies
+namespace Wino.Core.Domain.Models.Calendar.CalendarTypeStrategies
{
public class WeekCalendarDrawingStrategy : BaseCalendarTypeDrawingStrategy
{
- public WeekCalendarDrawingStrategy(CalendarSettings settings) : base(settings, Core.Domain.Enums.CalendarDisplayType.Week) { }
+ public WeekCalendarDrawingStrategy(CalendarSettings settings) : base(settings, Enums.CalendarDisplayType.Week) { }
public override DateRange GetNextDateRange(DateRange CurrentDateRange, int DayDisplayCount)
=> new DateRange(CurrentDateRange.EndDate, CurrentDateRange.EndDate.AddDays(7 * 2));
diff --git a/Wino.Core.Domain/Models/Requests/RequestBase.cs b/Wino.Core.Domain/Models/Requests/RequestBase.cs
index 9b354bf4..3f65aca1 100644
--- a/Wino.Core.Domain/Models/Requests/RequestBase.cs
+++ b/Wino.Core.Domain/Models/Requests/RequestBase.cs
@@ -1,34 +1,40 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Domain.Models.Requests
{
- public abstract record RequestBase(MailCopy Item, MailSynchronizerOperation Operation) : IRequest
- where TBatchRequestType : IBatchChangeRequest
+ public abstract record RequestBase where TOperation : Enum
{
- public abstract IBatchChangeRequest CreateBatch(IEnumerable requests);
- public abstract void ApplyUIChanges();
- public abstract void RevertUIChanges();
-
+ public virtual void ApplyUIChanges() { }
+ public virtual void RevertUIChanges() { }
public virtual int ResynchronizationDelay => 0;
+ public abstract TOperation Operation { get; }
+ public virtual object GroupingKey() { return Operation; }
}
- public abstract record FolderRequestBase(MailItemFolder Folder, MailSynchronizerOperation Operation) : IFolderRequest
+ public abstract record MailRequestBase(MailCopy Item) : RequestBase, IMailActionRequest
{
- public abstract void ApplyUIChanges();
- public abstract void RevertUIChanges();
-
- public virtual int ResynchronizationDelay => 0;
}
- public abstract record BatchRequestBase(IEnumerable Items, MailSynchronizerOperation Operation) : IBatchChangeRequest
+ public abstract record FolderRequestBase(MailItemFolder Folder, FolderSynchronizerOperation Operation) : IFolderActionRequest
{
public abstract void ApplyUIChanges();
public abstract void RevertUIChanges();
public virtual int ResynchronizationDelay => 0;
- public virtual bool ExecuteSerialBatch => false;
+
+ public virtual object GroupingKey() { return Operation; }
+ }
+
+ public class BatchCollection : List, IUIChangeRequest where TRequestType : IUIChangeRequest
+ {
+ public BatchCollection(IEnumerable collection) : base(collection)
+ {
+ }
+ public void ApplyUIChanges() => ForEach(x => x.ApplyUIChanges());
+ public void RevertUIChanges() => ForEach(x => x.RevertUIChanges());
}
}
diff --git a/Wino.Core/Extensions/ListExtensions.cs b/Wino.Core/Extensions/ListExtensions.cs
index 7330c44e..d0f89781 100644
--- a/Wino.Core/Extensions/ListExtensions.cs
+++ b/Wino.Core/Extensions/ListExtensions.cs
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Wino.Core.Domain.Enums;
-using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Extensions
{
@@ -19,40 +17,5 @@ namespace Wino.Core.Extensions
return nodes.Concat(descendants);
}
-
- public static IEnumerable CreateBatch(this IEnumerable> items)
- {
- IBatchChangeRequest batch = null;
-
- foreach (var group in items)
- {
- var key = group.Key;
- }
-
- yield return batch;
- }
-
- public static void AddSorted(this List @this, T item) where T : IComparable
- {
- if (@this.Count == 0)
- {
- @this.Add(item);
- return;
- }
- if (@this[@this.Count - 1].CompareTo(item) <= 0)
- {
- @this.Add(item);
- return;
- }
- if (@this[0].CompareTo(item) >= 0)
- {
- @this.Insert(0, item);
- return;
- }
- int index = @this.BinarySearch(item);
- if (index < 0)
- index = ~index;
- @this.Insert(index, item);
- }
}
}
diff --git a/Wino.Core/Integration/Json/ServerRequestTypeInfoResolver.cs b/Wino.Core/Integration/Json/ServerRequestTypeInfoResolver.cs
index 3a38f6ae..ff664d0c 100644
--- a/Wino.Core/Integration/Json/ServerRequestTypeInfoResolver.cs
+++ b/Wino.Core/Integration/Json/ServerRequestTypeInfoResolver.cs
@@ -2,7 +2,8 @@
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem;
-using Wino.Core.Requests;
+using Wino.Core.Requests.Folder;
+using Wino.Core.Requests.Mail;
namespace Wino.Core.Integration.Json
{
diff --git a/Wino.Core/Misc/RequestComparer.cs b/Wino.Core/Misc/RequestComparer.cs
deleted file mode 100644
index e884e5ea..00000000
--- a/Wino.Core/Misc/RequestComparer.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Collections.Generic;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Requests;
-
-namespace Wino.Core.Misc
-{
- ///
- /// This is incomplete.
- ///
- internal class RequestComparer : IEqualityComparer
- {
- public bool Equals(IRequestBase x, IRequestBase y)
- {
- if (x is MoveRequest sourceMoveRequest && y is MoveRequest targetMoveRequest)
- {
- return sourceMoveRequest.FromFolder.Id == targetMoveRequest.FromFolder.Id && sourceMoveRequest.ToFolder.Id == targetMoveRequest.ToFolder.Id;
- }
- else if (x is ChangeFlagRequest sourceFlagRequest && y is ChangeFlagRequest targetFlagRequest)
- {
- return sourceFlagRequest.IsFlagged == targetFlagRequest.IsFlagged;
- }
- else if (x is MarkReadRequest sourceMarkReadRequest && y is MarkReadRequest targetMarkReadRequest)
- {
- return sourceMarkReadRequest.Item.IsRead == targetMarkReadRequest.Item.IsRead;
- }
- else if (x is DeleteRequest sourceDeleteRequest && y is DeleteRequest targetDeleteRequest)
- {
- return sourceDeleteRequest.MailItem.AssignedFolder.Id == targetDeleteRequest.MailItem.AssignedFolder.Id;
- }
-
- return true;
- }
-
- public int GetHashCode(IRequestBase obj) => obj.Operation.GetHashCode();
- }
-}
diff --git a/Wino.Core/Requests/AlwaysMoveToRequest.cs b/Wino.Core/Requests/AlwaysMoveToRequest.cs
deleted file mode 100644
index 35f2d995..00000000
--- a/Wino.Core/Requests/AlwaysMoveToRequest.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using System.Collections.Generic;
-using System.ComponentModel;
-using Wino.Core.Domain.Entities.Mail;
-using Wino.Core.Domain.Enums;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Domain.Models.Requests;
-
-namespace Wino.Core.Requests
-{
- public record AlwaysMoveToRequest(MailCopy Item, bool MoveToFocused) : RequestBase(Item, MailSynchronizerOperation.AlwaysMoveTo)
- {
- public override IBatchChangeRequest CreateBatch(IEnumerable matchingItems)
- => new BatchAlwaysMoveToRequest(matchingItems, MoveToFocused);
-
- public override void ApplyUIChanges()
- {
-
- }
-
- public override void RevertUIChanges()
- {
-
- }
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public record BatchAlwaysMoveToRequest(IEnumerable Items, bool MoveToFocused) : BatchRequestBase(Items, MailSynchronizerOperation.AlwaysMoveTo)
- {
- public override void ApplyUIChanges()
- {
-
- }
-
- public override void RevertUIChanges()
- {
-
- }
- }
-}
diff --git a/Wino.Core/Requests/Bundles/RequestBundle.cs b/Wino.Core/Requests/Bundles/RequestBundle.cs
index 2f73e2dc..7f8fe6e9 100644
--- a/Wino.Core/Requests/Bundles/RequestBundle.cs
+++ b/Wino.Core/Requests/Bundles/RequestBundle.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Threading;
@@ -8,25 +7,9 @@ using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Requests.Bundles
{
- ///
- /// Bundle that encapsulates batch request and native request without a response.
- ///
- /// Http type for each integrator. eg. ClientServiceRequest for Gmail and RequestInformation for Microsoft Graph.
- /// Native type to send via http.
- /// Batch request that is generated by base synchronizer.
- public record HttpRequestBundle(TRequest NativeRequest, IRequestBase Request) : IRequestBundle
+ public record HttpRequestBundle(TRequest NativeRequest, IUIChangeRequest UIChangeRequest, IRequestBase Request = null) : IRequestBundle
{
public string BundleId { get; set; } = string.Empty;
-
- public override string ToString()
- {
- if (Request is IRequest singleRequest)
- return $"Single {singleRequest.Operation}. No response.";
- else if (Request is IBatchChangeRequest batchChangeRequest)
- return $"Batch {batchChangeRequest.Operation} for {batchChangeRequest.Items.Count()} items. No response.";
- else
- return "Unknown http request bundle.";
- }
}
///
@@ -43,15 +26,5 @@ namespace Wino.Core.Requests.Bundles
return JsonSerializer.Deserialize(content) ?? throw new InvalidOperationException("Invalid Http Response Deserialization");
}
-
- public override string ToString()
- {
- if (Request is IRequest singleRequest)
- return $"Single {singleRequest.Operation}. Expecting '{typeof(TResponse).FullName}' type.";
- else if (Request is IBatchChangeRequest batchChangeRequest)
- return $"Batch {batchChangeRequest.Operation} for {batchChangeRequest.Items.Count()} items. Expecting '{typeof(TResponse).FullName}' type.";
- else
- return "Unknown http request bundle.";
- }
}
}
diff --git a/Wino.Core/Requests/Bundles/TaskRequestBundle.cs b/Wino.Core/Requests/Bundles/TaskRequestBundle.cs
index 32b0991e..96e0bb69 100644
--- a/Wino.Core/Requests/Bundles/TaskRequestBundle.cs
+++ b/Wino.Core/Requests/Bundles/TaskRequestBundle.cs
@@ -5,19 +5,27 @@ using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Requests.Bundles
{
- //public abstract record TaskRequestBundleBase()
- //{
- // public abstract Task ExecuteAsync(ImapClient executorImapClient);
- //}
+ public class ImapRequest
+ {
+ public Func IntegratorTask { get; }
+ public IRequestBase Request { get; }
- //public record TaskRequestBundle(Func NativeRequest) : TaskRequestBundleBase
- //{
- // public override async Task ExecuteAsync(ImapClient executorImapClient) => await NativeRequest(executorImapClient).ConfigureAwait(false);
- //}
+ public ImapRequest(Func integratorTask, IRequestBase request)
+ {
+ IntegratorTask = integratorTask;
+ Request = request;
+ }
+ }
- public record ImapRequest(Func IntegratorTask, IRequestBase Request) { }
+ public class ImapRequest : ImapRequest where TRequestBaseType : IRequestBase
+ {
+ public ImapRequest(Func integratorTask, TRequestBaseType request)
+ : base((client, request) => integratorTask(client, (TRequestBaseType)request), request)
+ {
+ }
+ }
- public record ImapRequestBundle(ImapRequest NativeRequest, IRequestBase Request) : IRequestBundle
+ public record ImapRequestBundle(ImapRequest NativeRequest, IRequestBase Request, IUIChangeRequest UIChangeRequest) : IRequestBundle
{
public string BundleId { get; set; } = Guid.NewGuid().ToString();
}
diff --git a/Wino.Core/Requests/ChangeFlagRequest.cs b/Wino.Core/Requests/ChangeFlagRequest.cs
deleted file mode 100644
index 47aa0018..00000000
--- a/Wino.Core/Requests/ChangeFlagRequest.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using CommunityToolkit.Mvvm.Messaging;
-using MoreLinq;
-using Wino.Core.Domain.Entities.Mail;
-using Wino.Core.Domain.Enums;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Domain.Models.Requests;
-using Wino.Messaging.UI;
-
-namespace Wino.Core.Requests
-{
- public record ChangeFlagRequest(MailCopy Item, bool IsFlagged) : RequestBase(Item, MailSynchronizerOperation.ChangeFlag),
- ICustomFolderSynchronizationRequest
- {
- public List SynchronizationFolderIds => [Item.FolderId];
-
- public override IBatchChangeRequest CreateBatch(IEnumerable matchingItems)
- => new BatchChangeFlagRequest(matchingItems, IsFlagged);
-
- public override void ApplyUIChanges()
- {
- Item.IsFlagged = IsFlagged;
-
- WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item));
- }
-
- public override void RevertUIChanges()
- {
- Item.IsFlagged = !IsFlagged;
-
- WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item));
- }
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public record BatchChangeFlagRequest(IEnumerable Items, bool IsFlagged) : BatchRequestBase(Items, MailSynchronizerOperation.ChangeFlag)
- {
- public override void ApplyUIChanges()
- {
- Items.ForEach(item =>
- {
- item.Item.IsFlagged = IsFlagged;
-
- WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(item.Item));
- });
- }
-
- public override void RevertUIChanges()
- {
- Items.ForEach(item =>
- {
- item.Item.IsFlagged = !IsFlagged;
-
- WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(item.Item));
- });
- }
- }
-}
diff --git a/Wino.Core/Requests/CreateDraftRequest.cs b/Wino.Core/Requests/CreateDraftRequest.cs
deleted file mode 100644
index 026c5d4e..00000000
--- a/Wino.Core/Requests/CreateDraftRequest.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using CommunityToolkit.Mvvm.Messaging;
-using MoreLinq;
-using Wino.Core.Domain.Enums;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Domain.Models.MailItem;
-using Wino.Core.Domain.Models.Requests;
-using Wino.Messaging.UI;
-
-namespace Wino.Core.Requests
-{
- public record CreateDraftRequest(DraftPreparationRequest DraftPreperationRequest)
- : RequestBase(DraftPreperationRequest.CreatedLocalDraftCopy, MailSynchronizerOperation.CreateDraft),
- ICustomFolderSynchronizationRequest
- {
- public List SynchronizationFolderIds =>
- [
- DraftPreperationRequest.CreatedLocalDraftCopy.AssignedFolder.Id
- ];
-
- public override IBatchChangeRequest CreateBatch(IEnumerable matchingItems)
- => new BatchCreateDraftRequest(matchingItems, DraftPreperationRequest);
-
- public override void ApplyUIChanges()
- {
- // No need for it since Draft folder is automatically navigated and draft item is added + selected.
- // We only need to revert changes in case of network fails to create the draft.
- }
-
- public override void RevertUIChanges()
- {
- WeakReferenceMessenger.Default.Send(new MailRemovedMessage(Item));
- }
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public record class BatchCreateDraftRequest(IEnumerable Items, DraftPreparationRequest DraftPreperationRequest)
- : BatchRequestBase(Items, MailSynchronizerOperation.CreateDraft)
- {
- public override void ApplyUIChanges()
- {
- // No need for it since Draft folder is automatically navigated and draft item is added + selected.
- // We only need to revert changes in case of network fails to create the draft.
- }
-
- public override void RevertUIChanges()
- {
- Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailRemovedMessage(item.Item)));
- }
- }
-}
diff --git a/Wino.Core/Requests/EmptyFolderRequest.cs b/Wino.Core/Requests/Folder/EmptyFolderRequest.cs
similarity index 83%
rename from Wino.Core/Requests/EmptyFolderRequest.cs
rename to Wino.Core/Requests/Folder/EmptyFolderRequest.cs
index 13fa882e..8ae559c2 100644
--- a/Wino.Core/Requests/EmptyFolderRequest.cs
+++ b/Wino.Core/Requests/Folder/EmptyFolderRequest.cs
@@ -7,9 +7,9 @@ using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;
using Wino.Messaging.UI;
-namespace Wino.Core.Requests
+namespace Wino.Core.Requests.Folder
{
- public record EmptyFolderRequest(MailItemFolder Folder, List MailsToDelete) : FolderRequestBase(Folder, MailSynchronizerOperation.EmptyFolder), ICustomFolderSynchronizationRequest
+ public record EmptyFolderRequest(MailItemFolder Folder, List MailsToDelete) : FolderRequestBase(Folder, FolderSynchronizerOperation.EmptyFolder), ICustomFolderSynchronizationRequest
{
public override void ApplyUIChanges()
{
diff --git a/Wino.Core/Requests/MarkFolderAsReadRequest.cs b/Wino.Core/Requests/Folder/MarkFolderAsReadRequest.cs
similarity index 84%
rename from Wino.Core/Requests/MarkFolderAsReadRequest.cs
rename to Wino.Core/Requests/Folder/MarkFolderAsReadRequest.cs
index 9703247b..17e989b2 100644
--- a/Wino.Core/Requests/MarkFolderAsReadRequest.cs
+++ b/Wino.Core/Requests/Folder/MarkFolderAsReadRequest.cs
@@ -7,9 +7,9 @@ using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;
using Wino.Messaging.UI;
-namespace Wino.Core.Requests
+namespace Wino.Core.Requests.Folder
{
- public record MarkFolderAsReadRequest(MailItemFolder Folder, List MailsToMarkRead) : FolderRequestBase(Folder, MailSynchronizerOperation.MarkFolderRead), ICustomFolderSynchronizationRequest
+ public record MarkFolderAsReadRequest(MailItemFolder Folder, List MailsToMarkRead) : FolderRequestBase(Folder, FolderSynchronizerOperation.MarkFolderRead), ICustomFolderSynchronizationRequest
{
public override void ApplyUIChanges()
{
diff --git a/Wino.Core/Requests/RenameFolderRequest.cs b/Wino.Core/Requests/Folder/RenameFolderRequest.cs
similarity index 89%
rename from Wino.Core/Requests/RenameFolderRequest.cs
rename to Wino.Core/Requests/Folder/RenameFolderRequest.cs
index b42f8013..eada5e7d 100644
--- a/Wino.Core/Requests/RenameFolderRequest.cs
+++ b/Wino.Core/Requests/Folder/RenameFolderRequest.cs
@@ -4,9 +4,9 @@ using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Requests;
using Wino.Messaging.UI;
-namespace Wino.Core.Requests
+namespace Wino.Core.Requests.Folder
{
- public record RenameFolderRequest(MailItemFolder Folder, string CurrentFolderName, string NewFolderName) : FolderRequestBase(Folder, MailSynchronizerOperation.RenameFolder)
+ public record RenameFolderRequest(MailItemFolder Folder, string CurrentFolderName, string NewFolderName) : FolderRequestBase(Folder, FolderSynchronizerOperation.RenameFolder)
{
public override void ApplyUIChanges()
{
diff --git a/Wino.Core/Requests/Mail/AlwaysMoveToRequest.cs b/Wino.Core/Requests/Mail/AlwaysMoveToRequest.cs
new file mode 100644
index 00000000..31cc64bd
--- /dev/null
+++ b/Wino.Core/Requests/Mail/AlwaysMoveToRequest.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using Wino.Core.Domain.Entities.Mail;
+using Wino.Core.Domain.Enums;
+using Wino.Core.Domain.Models.Requests;
+
+namespace Wino.Core.Requests.Mail
+{
+ public record AlwaysMoveToRequest(MailCopy Item, bool MoveToFocused) : MailRequestBase(Item)
+ {
+ public override MailSynchronizerOperation Operation => MailSynchronizerOperation.AlwaysMoveTo;
+ }
+
+ public class BatchAlwaysMoveToRequest : BatchCollection
+ {
+ public BatchAlwaysMoveToRequest(IEnumerable collection) : base(collection)
+ {
+ }
+ }
+}
diff --git a/Wino.Core/Requests/ArchiveRequest.cs b/Wino.Core/Requests/Mail/ArchiveRequest.cs
similarity index 59%
rename from Wino.Core/Requests/ArchiveRequest.cs
rename to Wino.Core/Requests/Mail/ArchiveRequest.cs
index 3e957541..bc37bff3 100644
--- a/Wino.Core/Requests/ArchiveRequest.cs
+++ b/Wino.Core/Requests/Mail/ArchiveRequest.cs
@@ -1,15 +1,13 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
-using MoreLinq;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;
using Wino.Messaging.UI;
-namespace Wino.Core.Requests
+namespace Wino.Core.Requests.Mail
{
///
/// Archive message request.
@@ -20,7 +18,8 @@ namespace Wino.Core.Requests
/// Mail to archive
/// Source folder.
/// Optional Target folder. Required for ImapSynchronizer and OutlookSynchronizer.
- public record ArchiveRequest(bool IsArchiving, MailCopy Item, MailItemFolder FromFolder, MailItemFolder ToFolder = null) : RequestBase(Item, MailSynchronizerOperation.Archive), ICustomFolderSynchronizationRequest
+ public record ArchiveRequest(bool IsArchiving, MailCopy Item, MailItemFolder FromFolder, MailItemFolder ToFolder = null)
+ : MailRequestBase(Item), ICustomFolderSynchronizationRequest
{
public List SynchronizationFolderIds
{
@@ -37,8 +36,7 @@ namespace Wino.Core.Requests
}
}
- public override IBatchChangeRequest CreateBatch(IEnumerable matchingItems)
- => new BatchArchiveRequest(IsArchiving, matchingItems, FromFolder, ToFolder);
+ public override MailSynchronizerOperation Operation => MailSynchronizerOperation.Archive;
public override void ApplyUIChanges()
{
@@ -51,17 +49,10 @@ namespace Wino.Core.Requests
}
}
- [EditorBrowsable(EditorBrowsableState.Never)]
- public record BatchArchiveRequest(bool IsArchiving, IEnumerable Items, MailItemFolder FromFolder, MailItemFolder ToFolder = null) : BatchRequestBase(Items, MailSynchronizerOperation.Archive)
+ public class BatchArchiveRequest : BatchCollection
{
- public override void ApplyUIChanges()
+ public BatchArchiveRequest(IEnumerable collection) : base(collection)
{
- Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailRemovedMessage(item.Item)));
- }
-
- public override void RevertUIChanges()
- {
- Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailAddedMessage(item.Item)));
}
}
}
diff --git a/Wino.Core/Requests/Mail/ChangeFlagRequest.cs b/Wino.Core/Requests/Mail/ChangeFlagRequest.cs
new file mode 100644
index 00000000..56789c31
--- /dev/null
+++ b/Wino.Core/Requests/Mail/ChangeFlagRequest.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using CommunityToolkit.Mvvm.Messaging;
+using Wino.Core.Domain.Entities.Mail;
+using Wino.Core.Domain.Enums;
+using Wino.Core.Domain.Interfaces;
+using Wino.Core.Domain.Models.Requests;
+using Wino.Messaging.UI;
+
+namespace Wino.Core.Requests.Mail
+{
+ public record ChangeFlagRequest(MailCopy Item, bool IsFlagged) : MailRequestBase(Item),
+ ICustomFolderSynchronizationRequest
+ {
+ public List SynchronizationFolderIds => [Item.FolderId];
+
+ public override MailSynchronizerOperation Operation => MailSynchronizerOperation.ChangeFlag;
+
+ public override void ApplyUIChanges()
+ {
+ Item.IsFlagged = IsFlagged;
+
+ WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item));
+ }
+
+ public override void RevertUIChanges()
+ {
+ Item.IsFlagged = !IsFlagged;
+
+ WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item));
+ }
+ }
+
+ public class BatchChangeFlagRequest : BatchCollection
+ {
+ public BatchChangeFlagRequest(IEnumerable collection) : base(collection)
+ {
+ }
+ }
+}
diff --git a/Wino.Core/Requests/Mail/CreateDraftRequest.cs b/Wino.Core/Requests/Mail/CreateDraftRequest.cs
new file mode 100644
index 00000000..beb09fa6
--- /dev/null
+++ b/Wino.Core/Requests/Mail/CreateDraftRequest.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using CommunityToolkit.Mvvm.Messaging;
+using Wino.Core.Domain.Enums;
+using Wino.Core.Domain.Interfaces;
+using Wino.Core.Domain.Models.MailItem;
+using Wino.Core.Domain.Models.Requests;
+using Wino.Messaging.UI;
+
+namespace Wino.Core.Requests.Mail
+{
+ public record CreateDraftRequest(DraftPreparationRequest DraftPreperationRequest)
+ : MailRequestBase(DraftPreperationRequest.CreatedLocalDraftCopy),
+ ICustomFolderSynchronizationRequest
+ {
+ public List SynchronizationFolderIds =>
+ [
+ DraftPreperationRequest.CreatedLocalDraftCopy.AssignedFolder.Id
+ ];
+
+ public override MailSynchronizerOperation Operation => MailSynchronizerOperation.CreateDraft;
+
+ public override void RevertUIChanges()
+ {
+ WeakReferenceMessenger.Default.Send(new MailRemovedMessage(Item));
+ }
+ }
+}
diff --git a/Wino.Core/Requests/DeleteRequest.cs b/Wino.Core/Requests/Mail/DeleteRequest.cs
similarity index 52%
rename from Wino.Core/Requests/DeleteRequest.cs
rename to Wino.Core/Requests/Mail/DeleteRequest.cs
index 5d929f53..de6e9ffb 100644
--- a/Wino.Core/Requests/DeleteRequest.cs
+++ b/Wino.Core/Requests/Mail/DeleteRequest.cs
@@ -1,27 +1,24 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
-using MoreLinq;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;
using Wino.Messaging.UI;
-namespace Wino.Core.Requests
+namespace Wino.Core.Requests.Mail
{
///
/// Hard delete request. This request will delete the mail item from the server without moving it to the trash folder.
///
/// Item to delete permanently.
- public record DeleteRequest(MailCopy MailItem) : RequestBase(MailItem, MailSynchronizerOperation.Delete),
+ public record DeleteRequest(MailCopy MailItem) : MailRequestBase(MailItem),
ICustomFolderSynchronizationRequest
{
public List SynchronizationFolderIds => [Item.FolderId];
- public override IBatchChangeRequest CreateBatch(IEnumerable matchingItems)
- => new BatchDeleteRequest(matchingItems);
+ public override MailSynchronizerOperation Operation => MailSynchronizerOperation.Delete;
public override void ApplyUIChanges()
{
@@ -34,17 +31,10 @@ namespace Wino.Core.Requests
}
}
- [EditorBrowsable(EditorBrowsableState.Never)]
- public record class BatchDeleteRequest(IEnumerable Items) : BatchRequestBase(Items, MailSynchronizerOperation.Delete)
+ public class BatchDeleteRequest : BatchCollection
{
- public override void ApplyUIChanges()
+ public BatchDeleteRequest(IEnumerable collection) : base(collection)
{
- Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailRemovedMessage(item.Item)));
- }
-
- public override void RevertUIChanges()
- {
- Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailAddedMessage(item.Item)));
}
}
}
diff --git a/Wino.Core/Requests/Mail/MarkReadRequest.cs b/Wino.Core/Requests/Mail/MarkReadRequest.cs
new file mode 100644
index 00000000..e5b80e44
--- /dev/null
+++ b/Wino.Core/Requests/Mail/MarkReadRequest.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using CommunityToolkit.Mvvm.Messaging;
+using Wino.Core.Domain.Entities.Mail;
+using Wino.Core.Domain.Enums;
+using Wino.Core.Domain.Interfaces;
+using Wino.Core.Domain.Models.Requests;
+using Wino.Messaging.UI;
+
+namespace Wino.Core.Requests.Mail
+{
+ public record MarkReadRequest(MailCopy Item, bool IsRead) : MailRequestBase(Item), ICustomFolderSynchronizationRequest
+ {
+ public List SynchronizationFolderIds => [Item.FolderId];
+
+ public override MailSynchronizerOperation Operation => MailSynchronizerOperation.MarkRead;
+
+ public override void ApplyUIChanges()
+ {
+ Item.IsRead = IsRead;
+
+ WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item));
+ }
+
+ public override void RevertUIChanges()
+ {
+ Item.IsRead = !IsRead;
+
+ WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item));
+ }
+ }
+
+ public class BatchMarkReadRequest : BatchCollection
+ {
+ public BatchMarkReadRequest(IEnumerable collection) : base(collection)
+ {
+ }
+ }
+}
diff --git a/Wino.Core/Requests/Mail/MoveRequest.cs b/Wino.Core/Requests/Mail/MoveRequest.cs
new file mode 100644
index 00000000..8fc198ef
--- /dev/null
+++ b/Wino.Core/Requests/Mail/MoveRequest.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using CommunityToolkit.Mvvm.Messaging;
+using Wino.Core.Domain.Entities.Mail;
+using Wino.Core.Domain.Enums;
+using Wino.Core.Domain.Interfaces;
+using Wino.Core.Domain.Models.Requests;
+using Wino.Messaging.UI;
+
+namespace Wino.Core.Requests.Mail
+{
+ public record MoveRequest(MailCopy Item, MailItemFolder FromFolder, MailItemFolder ToFolder)
+ : MailRequestBase(Item), ICustomFolderSynchronizationRequest
+ {
+ public List SynchronizationFolderIds => new() { FromFolder.Id, ToFolder.Id };
+
+ public override MailSynchronizerOperation Operation => MailSynchronizerOperation.Move;
+
+ public override void ApplyUIChanges()
+ {
+ WeakReferenceMessenger.Default.Send(new MailRemovedMessage(Item));
+ }
+
+ public override void RevertUIChanges()
+ {
+ WeakReferenceMessenger.Default.Send(new MailAddedMessage(Item));
+ }
+ }
+
+ public class BatchMoveRequest : BatchCollection, IUIChangeRequest
+ {
+ public BatchMoveRequest(IEnumerable collection) : base(collection)
+ {
+ }
+ }
+}
diff --git a/Wino.Core/Requests/Mail/MoveToFocusedRequest.cs b/Wino.Core/Requests/Mail/MoveToFocusedRequest.cs
new file mode 100644
index 00000000..f9b4fea6
--- /dev/null
+++ b/Wino.Core/Requests/Mail/MoveToFocusedRequest.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using Wino.Core.Domain.Entities.Mail;
+using Wino.Core.Domain.Enums;
+using Wino.Core.Domain.Models.Requests;
+
+namespace Wino.Core.Requests.Mail
+{
+ public record MoveToFocusedRequest(MailCopy Item, bool MoveToFocused) : MailRequestBase(Item)
+ {
+ public override MailSynchronizerOperation Operation => MailSynchronizerOperation.MoveToFocused;
+ }
+
+ public class BatchMoveToFocusedRequest : BatchCollection
+ {
+ public BatchMoveToFocusedRequest(IEnumerable collection) : base(collection)
+ {
+ }
+ }
+}
diff --git a/Wino.Core/Requests/Mail/SendDraftRequest.cs b/Wino.Core/Requests/Mail/SendDraftRequest.cs
new file mode 100644
index 00000000..0dfc56fe
--- /dev/null
+++ b/Wino.Core/Requests/Mail/SendDraftRequest.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using CommunityToolkit.Mvvm.Messaging;
+using Wino.Core.Domain.Enums;
+using Wino.Core.Domain.Interfaces;
+using Wino.Core.Domain.Models.MailItem;
+using Wino.Core.Domain.Models.Requests;
+using Wino.Messaging.UI;
+
+namespace Wino.Core.Requests.Mail
+{
+ public record SendDraftRequest(SendDraftPreparationRequest Request)
+ : MailRequestBase(Request.MailItem),
+ ICustomFolderSynchronizationRequest
+ {
+ public List SynchronizationFolderIds
+ {
+ get
+ {
+ var folderIds = new List { Request.DraftFolder.Id };
+
+ if (Request.SentFolder != null)
+ {
+ folderIds.Add(Request.SentFolder.Id);
+ }
+
+ return folderIds;
+ }
+ }
+
+ public override MailSynchronizerOperation Operation => MailSynchronizerOperation.Send;
+
+ public override void ApplyUIChanges()
+ {
+ WeakReferenceMessenger.Default.Send(new MailRemovedMessage(Item));
+ }
+
+ public override void RevertUIChanges()
+ {
+ WeakReferenceMessenger.Default.Send(new MailAddedMessage(Item));
+ }
+ }
+}
diff --git a/Wino.Core/Requests/MarkReadRequest.cs b/Wino.Core/Requests/MarkReadRequest.cs
deleted file mode 100644
index a3f38e06..00000000
--- a/Wino.Core/Requests/MarkReadRequest.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using CommunityToolkit.Mvvm.Messaging;
-using MoreLinq;
-using Wino.Core.Domain.Entities.Mail;
-using Wino.Core.Domain.Enums;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Domain.Models.Requests;
-using Wino.Messaging.UI;
-
-namespace Wino.Core.Requests
-{
- public record MarkReadRequest(MailCopy Item, bool IsRead) : RequestBase(Item, MailSynchronizerOperation.MarkRead),
- ICustomFolderSynchronizationRequest
- {
- public List SynchronizationFolderIds => [Item.FolderId];
-
- public override IBatchChangeRequest CreateBatch(IEnumerable matchingItems)
- => new BatchMarkReadRequest(matchingItems, IsRead);
-
- public override void ApplyUIChanges()
- {
- Item.IsRead = IsRead;
-
- WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item));
- }
-
- public override void RevertUIChanges()
- {
- Item.IsRead = !IsRead;
-
- WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item));
- }
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public record BatchMarkReadRequest(IEnumerable Items, bool IsRead) : BatchRequestBase(Items, MailSynchronizerOperation.MarkRead)
- {
- public override void ApplyUIChanges()
- {
- Items.ForEach(item =>
- {
- item.Item.IsRead = IsRead;
-
- WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(item.Item));
- });
- }
-
- public override void RevertUIChanges()
- {
- Items.ForEach(item =>
- {
- item.Item.IsRead = !IsRead;
-
- WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(item.Item));
- });
- }
- }
-}
diff --git a/Wino.Core/Requests/MoveRequest.cs b/Wino.Core/Requests/MoveRequest.cs
deleted file mode 100644
index d07a78a8..00000000
--- a/Wino.Core/Requests/MoveRequest.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using CommunityToolkit.Mvvm.Messaging;
-using MoreLinq;
-using Wino.Core.Domain.Entities.Mail;
-using Wino.Core.Domain.Enums;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Domain.Models.Requests;
-using Wino.Messaging.UI;
-
-namespace Wino.Core.Requests
-{
- public record MoveRequest(MailCopy Item, MailItemFolder FromFolder, MailItemFolder ToFolder)
- : RequestBase(Item, MailSynchronizerOperation.Move), ICustomFolderSynchronizationRequest
- {
- public List SynchronizationFolderIds => new() { FromFolder.Id, ToFolder.Id };
-
- public override IBatchChangeRequest CreateBatch(IEnumerable matchingItems)
- => new BatchMoveRequest(matchingItems, FromFolder, ToFolder);
-
- public override void ApplyUIChanges()
- {
- WeakReferenceMessenger.Default.Send(new MailRemovedMessage(Item));
- }
-
- public override void RevertUIChanges()
- {
- WeakReferenceMessenger.Default.Send(new MailAddedMessage(Item));
- }
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public record BatchMoveRequest(IEnumerable Items, MailItemFolder FromFolder, MailItemFolder ToFolder) : BatchRequestBase(Items, MailSynchronizerOperation.Move)
- {
- public override void ApplyUIChanges()
- {
- Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailRemovedMessage(item.Item)));
- }
-
- public override void RevertUIChanges()
- {
- Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailAddedMessage(item.Item)));
- }
-
- public override int ResynchronizationDelay => 3000;
- }
-}
diff --git a/Wino.Core/Requests/MoveToFocusedRequest.cs b/Wino.Core/Requests/MoveToFocusedRequest.cs
deleted file mode 100644
index 20a50859..00000000
--- a/Wino.Core/Requests/MoveToFocusedRequest.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System.Collections.Generic;
-using System.ComponentModel;
-using Wino.Core.Domain.Entities.Mail;
-using Wino.Core.Domain.Enums;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Domain.Models.Requests;
-
-namespace Wino.Core.Requests
-{
- public record MoveToFocusedRequest(MailCopy Item, bool MoveToFocused) : RequestBase(Item, MailSynchronizerOperation.Move)
- {
- public override IBatchChangeRequest CreateBatch(IEnumerable matchingItems)
- => new BatchMoveToFocusedRequest(matchingItems, MoveToFocused);
-
- public override void ApplyUIChanges() { }
-
- public override void RevertUIChanges() { }
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public record BatchMoveToFocusedRequest(IEnumerable Items, bool MoveToFocused) : BatchRequestBase(Items, MailSynchronizerOperation.Move)
- {
- public override void ApplyUIChanges() { }
-
- public override void RevertUIChanges() { }
- }
-}
diff --git a/Wino.Core/Requests/SendDraftRequest.cs b/Wino.Core/Requests/SendDraftRequest.cs
deleted file mode 100644
index 0effa59f..00000000
--- a/Wino.Core/Requests/SendDraftRequest.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using CommunityToolkit.Mvvm.Messaging;
-using MoreLinq;
-using Wino.Core.Domain.Enums;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Domain.Models.MailItem;
-using Wino.Core.Domain.Models.Requests;
-using Wino.Messaging.UI;
-
-namespace Wino.Core.Requests
-{
- public record SendDraftRequest(SendDraftPreparationRequest Request)
- : RequestBase(Request.MailItem, MailSynchronizerOperation.Send),
- ICustomFolderSynchronizationRequest
- {
- public List SynchronizationFolderIds
- {
- get
- {
- var folderIds = new List { Request.DraftFolder.Id };
-
- if (Request.SentFolder != null)
- {
- folderIds.Add(Request.SentFolder.Id);
- }
-
- return folderIds;
- }
- }
-
- public override IBatchChangeRequest CreateBatch(IEnumerable matchingItems)
- => new BatchSendDraftRequestRequest(matchingItems, Request);
-
- public override void ApplyUIChanges()
- {
- WeakReferenceMessenger.Default.Send(new MailRemovedMessage(Item));
- }
-
- public override void RevertUIChanges()
- {
- WeakReferenceMessenger.Default.Send(new MailAddedMessage(Item));
- }
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public record BatchSendDraftRequestRequest(IEnumerable Items,
- SendDraftPreparationRequest Request) : BatchRequestBase(Items, MailSynchronizerOperation.Send)
- {
- public override void ApplyUIChanges()
- {
- Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailRemovedMessage(item.Item)));
- }
-
- public override void RevertUIChanges()
- {
- Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailAddedMessage(item.Item)));
- }
-
- public override int ResynchronizationDelay => 6000;
- public override bool ExecuteSerialBatch => true;
- }
-}
diff --git a/Wino.Core/Services/WinoRequestDelegator.cs b/Wino.Core/Services/WinoRequestDelegator.cs
index dd3e7941..6223a843 100644
--- a/Wino.Core/Services/WinoRequestDelegator.cs
+++ b/Wino.Core/Services/WinoRequestDelegator.cs
@@ -11,7 +11,7 @@ using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Synchronization;
-using Wino.Core.Requests;
+using Wino.Core.Requests.Mail;
using Wino.Messaging.Server;
namespace Wino.Core.Services
@@ -37,7 +37,7 @@ namespace Wino.Core.Services
public async Task ExecuteAsync(MailOperationPreperationRequest request)
{
- var requests = new List();
+ var requests = new List();
try
{
diff --git a/Wino.Core/Services/WinoRequestProcessor.cs b/Wino.Core/Services/WinoRequestProcessor.cs
index c1dff9d9..270d118a 100644
--- a/Wino.Core/Services/WinoRequestProcessor.cs
+++ b/Wino.Core/Services/WinoRequestProcessor.cs
@@ -9,7 +9,8 @@ using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
-using Wino.Core.Requests;
+using Wino.Core.Requests.Folder;
+using Wino.Core.Requests.Mail;
namespace Wino.Core.Services
{
@@ -17,7 +18,7 @@ namespace Wino.Core.Services
/// Intermediary processor for converting a user action to executable Wino requests.
/// Primarily responsible for batching requests by AccountId and FolderId.
///
- public class WinoRequestProcessor : BaseDatabaseService, IWinoRequestProcessor
+ public class WinoRequestProcessor : IWinoRequestProcessor
{
private readonly IFolderService _folderService;
private readonly IKeyPressService _keyPressService;
@@ -37,13 +38,12 @@ namespace Wino.Core.Services
new ToggleRequestRule(MailOperation.ClearFlag, MailOperation.SetFlag, new System.Func((item) => !item.IsFlagged)),
];
- public WinoRequestProcessor(IDatabaseService databaseService,
- IFolderService folderService,
+ public WinoRequestProcessor(IFolderService folderService,
IKeyPressService keyPressService,
IPreferencesService preferencesService,
IAccountService accountService,
IMailDialogService dialogService,
- IMailService mailService) : base(databaseService)
+ IMailService mailService)
{
_folderService = folderService;
_keyPressService = keyPressService;
@@ -53,7 +53,7 @@ namespace Wino.Core.Services
_mailService = mailService;
}
- public async Task> PrepareRequestsAsync(MailOperationPreperationRequest preperationRequest)
+ public async Task> PrepareRequestsAsync(MailOperationPreperationRequest preperationRequest)
{
var action = preperationRequest.Action;
var moveTargetStructure = preperationRequest.MoveTargetFolder;
@@ -89,7 +89,7 @@ namespace Wino.Core.Services
return default;
}
- var requests = new List();
+ var requests = new List();
// TODO: Fix: Collection was modified; enumeration operation may not execute
foreach (var item in preperationRequest.MailItems)
@@ -104,7 +104,7 @@ namespace Wino.Core.Services
return requests;
}
- private async Task GetSingleRequestAsync(MailCopy mailItem, MailOperation action, IMailItemFolder moveTargetStructure, bool shouldToggleActions)
+ private async Task GetSingleRequestAsync(MailCopy mailItem, MailOperation action, IMailItemFolder moveTargetStructure, bool shouldToggleActions)
{
if (mailItem.AssignedAccount == null) throw new ArgumentException(Translator.Exception_NullAssignedAccount);
if (mailItem.AssignedFolder == null) throw new ArgumentException(Translator.Exception_NullAssignedFolder);
@@ -215,11 +215,11 @@ namespace Wino.Core.Services
return null;
}
- public async Task PrepareFolderRequestAsync(FolderOperationPreperationRequest request)
+ public async Task PrepareFolderRequestAsync(FolderOperationPreperationRequest request)
{
if (request == null || request.Folder == null) return default;
- IRequestBase change = null;
+ IFolderActionRequest change = null;
var folder = request.Folder;
var operation = request.Action;
diff --git a/Wino.Core/Synchronizers/BaseMailSynchronizer.cs b/Wino.Core/Synchronizers/BaseMailSynchronizer.cs
index 8e6436c7..971e2225 100644
--- a/Wino.Core/Synchronizers/BaseMailSynchronizer.cs
+++ b/Wino.Core/Synchronizers/BaseMailSynchronizer.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
@@ -18,9 +17,9 @@ using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Synchronization;
-using Wino.Core.Misc;
-using Wino.Core.Requests;
using Wino.Core.Requests.Bundles;
+using Wino.Core.Requests.Folder;
+using Wino.Core.Requests.Mail;
using Wino.Messaging.UI;
namespace Wino.Core.Synchronizers
@@ -30,7 +29,7 @@ namespace Wino.Core.Synchronizers
private SemaphoreSlim synchronizationSemaphore = new(1);
private CancellationToken activeSynchronizationCancellationToken;
- protected ConcurrentBag changeRequestQueue = [];
+ protected List changeRequestQueue = [];
protected ILogger Logger = Log.ForContext>();
///
@@ -81,7 +80,7 @@ namespace Wino.Core.Synchronizers
///
/// Batched requests to execute. Integrator methods will only receive batched requests.
/// Cancellation token
- public abstract Task ExecuteNativeRequestsAsync(IEnumerable> batchedRequests, CancellationToken cancellationToken = default);
+ public abstract Task ExecuteNativeRequestsAsync(List> batchedRequests, CancellationToken cancellationToken = default);
///
/// Refreshes remote mail account profile if possible.
@@ -153,29 +152,69 @@ namespace Wino.Core.Synchronizers
{
activeSynchronizationCancellationToken = cancellationToken;
- var batches = CreateBatchRequests().Distinct();
+ State = AccountSynchronizerState.ExecutingRequests;
- if (batches.Any())
+ List> nativeRequests = new();
+
+ List requestCopies = new(changeRequestQueue);
+
+ var keys = changeRequestQueue.GroupBy(a => a.GroupingKey());
+
+ foreach (var group in keys)
{
- Logger.Information($"{batches?.Count() ?? 0} batched requests");
+ var key = group.Key;
- State = AccountSynchronizerState.ExecutingRequests;
-
- var nativeRequests = CreateNativeRequestBundles(batches);
-
- Console.WriteLine($"Prepared {nativeRequests.Count()} native requests");
-
- await ExecuteNativeRequestsAsync(nativeRequests, activeSynchronizationCancellationToken);
-
- PublishUnreadItemChanges();
-
- // Execute request sync options should be re-calculated after execution.
- // This is the part we decide which individual folders must be synchronized
- // after the batch request execution.
- if (options.Type == SynchronizationType.ExecuteRequests)
- options = GetSynchronizationOptionsAfterRequestExecution(batches);
+ if (key is MailSynchronizerOperation mailSynchronizerOperation)
+ {
+ switch (mailSynchronizerOperation)
+ {
+ case MailSynchronizerOperation.MarkRead:
+ nativeRequests.AddRange(MarkRead(new BatchMarkReadRequest(group.Cast())));
+ break;
+ case MailSynchronizerOperation.Move:
+ nativeRequests.AddRange(Move(new BatchMoveRequest(group.Cast())));
+ break;
+ case MailSynchronizerOperation.Delete:
+ nativeRequests.AddRange(Delete(new BatchDeleteRequest(group.Cast())));
+ break;
+ case MailSynchronizerOperation.CreateDraft:
+ nativeRequests.AddRange(CreateDraft(group.ElementAt(0) as CreateDraftRequest));
+ break;
+ case MailSynchronizerOperation.Send:
+ nativeRequests.AddRange(SendDraft(group.ElementAt(0) as SendDraftRequest));
+ break;
+ case MailSynchronizerOperation.ChangeFlag:
+ nativeRequests.AddRange(ChangeFlag(new BatchChangeFlagRequest(group.Cast())));
+ break;
+ case MailSynchronizerOperation.AlwaysMoveTo:
+ nativeRequests.AddRange(AlwaysMoveTo(new BatchAlwaysMoveToRequest(group.Cast())));
+ break;
+ case MailSynchronizerOperation.MoveToFocused:
+ nativeRequests.AddRange(MoveToFocused(new BatchMoveToFocusedRequest(group.Cast())));
+ break;
+ case MailSynchronizerOperation.Archive:
+ nativeRequests.AddRange(Archive(new BatchArchiveRequest(group.Cast())));
+ break;
+ default:
+ break;
+ }
+ }
}
+ changeRequestQueue.Clear();
+
+ Console.WriteLine($"Prepared {nativeRequests.Count()} native requests");
+
+ await ExecuteNativeRequestsAsync(nativeRequests, activeSynchronizationCancellationToken);
+
+ PublishUnreadItemChanges();
+
+ // Execute request sync options should be re-calculated after execution.
+ // This is the part we decide which individual folders must be synchronized
+ // after the batch request execution.
+ if (options.Type == SynchronizationType.ExecuteRequests)
+ options = GetSynchronizationOptionsAfterRequestExecution(requestCopies);
+
State = AccountSynchronizerState.Synchronizing;
await synchronizationSemaphore.WaitAsync(activeSynchronizationCancellationToken);
@@ -228,11 +267,11 @@ namespace Wino.Core.Synchronizers
bool shouldDelayExecution =
(Account.ProviderType == MailProviderType.Outlook || Account.ProviderType == MailProviderType.Office365)
- && batches.Any(a => a.ResynchronizationDelay > 0);
+ && requestCopies.Any(a => a.ResynchronizationDelay > 0);
if (shouldDelayExecution)
{
- var maxDelay = batches.Aggregate(0, (max, next) => Math.Max(max, next.ResynchronizationDelay));
+ var maxDelay = requestCopies.Aggregate(0, (max, next) => Math.Max(max, next.ResynchronizationDelay));
await Task.Delay(maxDelay);
}
@@ -290,120 +329,112 @@ namespace Wino.Core.Synchronizers
/// since all folders must be asynchronously opened/closed.
///
/// Batch request collection for all these single requests.
- private List CreateBatchRequests()
- {
- var batchList = new List();
- var comparer = new RequestComparer();
+ //private List CreateBatchRequests()
+ //{
+ // var batchList = new List();
+ // var comparer = new RequestComparer();
- while (changeRequestQueue.Count > 0)
- {
- if (changeRequestQueue.TryPeek(out IRequestBase request))
- {
- // Mail request, must be batched.
- if (request is IRequest mailRequest)
- {
- var equalItems = changeRequestQueue
- .Where(a => a is IRequest && comparer.Equals(a, request))
- .Cast()
- .ToList();
+ // while (changeRequestQueue.Count > 0)
+ // {
+ // if (changeRequestQueue.TryPeek(out IRequestBase request))
+ // {
+ // // Mail request, must be batched.
+ // if (request is IMailActionRequest mailRequest)
+ // {
+ // var equalItems = changeRequestQueue
+ // .Where(a => a is IMailActionRequest && comparer.Equals(a, request))
+ // .Cast()
+ // .ToList();
- batchList.Add(mailRequest.CreateBatch(equalItems));
+ // batchList.Add(mailRequest.CreateBatch(equalItems));
- // Remove these items from the queue.
- foreach (var item in equalItems)
- {
- changeRequestQueue.TryTake(out _);
- }
- }
- else if (changeRequestQueue.TryTake(out request))
- {
- // This is a folder operation.
- // There is no need to batch them since Users can't do folder ops in bulk.
+ // // Remove these items from the queue.
+ // foreach (var item in equalItems)
+ // {
+ // changeRequestQueue.TryTake(out _);
+ // }
+ // }
+ // else if (changeRequestQueue.TryTake(out request))
+ // {
+ // // This is a folder operation.
+ // // There is no need to batch them since Users can't do folder ops in bulk.
- batchList.Add(request);
- }
- }
- }
+ // batchList.Add(request);
+ // }
+ // }
+ // }
- return batchList;
- }
+ // return batchList;
+ //}
///
/// Converts batched requests into HTTP/Task calls that derived synchronizers can execute.
///
/// Batch requests to be converted.
/// Collection of native requests for individual synchronizer type.
- private IEnumerable> CreateNativeRequestBundles(IEnumerable batchChangeRequests)
- {
- IEnumerable>> GetNativeRequests()
- {
- foreach (var item in batchChangeRequests)
- {
- switch (item.Operation)
- {
- case MailSynchronizerOperation.Send:
- yield return SendDraft((BatchSendDraftRequestRequest)item);
- break;
- case MailSynchronizerOperation.MarkRead:
- yield return MarkRead((BatchMarkReadRequest)item);
- break;
- case MailSynchronizerOperation.Move:
- yield return Move((BatchMoveRequest)item);
- break;
- case MailSynchronizerOperation.Delete:
- yield return Delete((BatchDeleteRequest)item);
- break;
- case MailSynchronizerOperation.ChangeFlag:
- yield return ChangeFlag((BatchChangeFlagRequest)item);
- break;
- case MailSynchronizerOperation.AlwaysMoveTo:
- yield return AlwaysMoveTo((BatchAlwaysMoveToRequest)item);
- break;
- case MailSynchronizerOperation.MoveToFocused:
- yield return MoveToFocused((BatchMoveToFocusedRequest)item);
- break;
- case MailSynchronizerOperation.CreateDraft:
- yield return CreateDraft((BatchCreateDraftRequest)item);
- break;
- case MailSynchronizerOperation.RenameFolder:
- yield return RenameFolder((RenameFolderRequest)item);
- break;
- case MailSynchronizerOperation.EmptyFolder:
- yield return EmptyFolder((EmptyFolderRequest)item);
- break;
- case MailSynchronizerOperation.MarkFolderRead:
- yield return MarkFolderAsRead((MarkFolderAsReadRequest)item);
- break;
- case MailSynchronizerOperation.Archive:
- yield return Archive((BatchArchiveRequest)item);
- break;
- }
- }
- };
+ //private IEnumerable> CreateNativeRequestBundles(IEnumerable batchChangeRequests)
+ //{
+ // IEnumerable>> GetNativeRequests()
+ // {
+ // foreach (var item in batchChangeRequests)
+ // {
+ // switch (item.Operation)
+ // {
+ // case MailSynchronizerOperation.Send:
+ // yield return SendDraft((BatchSendDraftRequestRequest)item);
+ // break;
+ // case MailSynchronizerOperation.MarkRead:
+ // yield return MarkRead((BatchMarkReadRequest)item);
+ // break;
+ // case MailSynchronizerOperation.Move:
+ // yield return Move((BatchMoveRequest)item);
+ // break;
+ // case MailSynchronizerOperation.Delete:
+ // yield return Delete((BatchDeleteRequest)item);
+ // break;
+ // case MailSynchronizerOperation.ChangeFlag:
+ // yield return ChangeFlag((BatchChangeFlagRequest)item);
+ // break;
+ // case MailSynchronizerOperation.AlwaysMoveTo:
+ // yield return AlwaysMoveTo((BatchAlwaysMoveToRequest)item);
+ // break;
+ // case MailSynchronizerOperation.MoveToFocused:
+ // yield return MoveToFocused((BatchMoveToFocusedRequest)item);
+ // break;
+ // case MailSynchronizerOperation.CreateDraft:
+ // yield return CreateDraft((BatchCreateDraftRequest)item);
+ // break;
+ // case MailSynchronizerOperation.RenameFolder:
+ // yield return RenameFolder((RenameFolderRequest)item);
+ // break;
+ // case MailSynchronizerOperation.EmptyFolder:
+ // yield return EmptyFolder((EmptyFolderRequest)item);
+ // break;
+ // case MailSynchronizerOperation.MarkFolderRead:
+ // yield return MarkFolderAsRead((MarkFolderAsReadRequest)item);
+ // break;
+ // case MailSynchronizerOperation.Archive:
+ // yield return Archive((BatchArchiveRequest)item);
+ // break;
+ // }
+ // }
+ // };
- return GetNativeRequests().SelectMany(collections => collections);
- }
+ // return GetNativeRequests().SelectMany(collections => collections);
+ //}
///
/// Attempts to find out the best possible synchronization options after the batch request execution.
///
/// Batch requests to run in synchronization.
/// New synchronization options with minimal HTTP effort.
- private SynchronizationOptions GetSynchronizationOptionsAfterRequestExecution(IEnumerable requests)
+ private SynchronizationOptions GetSynchronizationOptionsAfterRequestExecution(List requests)
{
- List synchronizationFolderIds = new();
-
- if (requests.All(a => a is IBatchChangeRequest))
- {
- var requestsInsideBatches = requests.Cast().SelectMany(b => b.Items);
-
- // Gather FolderIds to synchronize.
- synchronizationFolderIds = requestsInsideBatches
+ List synchronizationFolderIds = requests
.Where(a => a is ICustomFolderSynchronizationRequest)
.Cast()
.SelectMany(a => a.SynchronizationFolderIds)
.ToList();
- }
var options = new SynchronizationOptions()
{
@@ -427,18 +458,20 @@ namespace Wino.Core.Synchronizers
}
public virtual bool DelaySendOperationSynchronization() => false;
- public virtual IEnumerable> Move(BatchMoveRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
- public virtual IEnumerable> ChangeFlag(BatchChangeFlagRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
- public virtual IEnumerable> MarkRead(BatchMarkReadRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
- public virtual IEnumerable> Delete(BatchDeleteRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
- public virtual IEnumerable> AlwaysMoveTo(BatchAlwaysMoveToRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
- public virtual IEnumerable> MoveToFocused(BatchMoveToFocusedRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
- public virtual IEnumerable> CreateDraft(BatchCreateDraftRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
- public virtual IEnumerable> SendDraft(BatchSendDraftRequestRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
- public virtual IEnumerable> RenameFolder(RenameFolderRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
- public virtual IEnumerable> EmptyFolder(EmptyFolderRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
- public virtual IEnumerable> MarkFolderAsRead(MarkFolderAsReadRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
- public virtual IEnumerable> Archive(BatchArchiveRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+ public virtual List> Move(BatchMoveRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+ public virtual List> ChangeFlag(BatchChangeFlagRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+ public virtual List> MarkRead(BatchMarkReadRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+ public virtual List> Delete(BatchDeleteRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+ public virtual List> AlwaysMoveTo(BatchAlwaysMoveToRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+ public virtual List> MoveToFocused(BatchMoveToFocusedRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+ public virtual List> CreateDraft(CreateDraftRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+ public virtual List> SendDraft(SendDraftRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+ public virtual List> Archive(BatchArchiveRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+
+ public virtual List> RenameFolder(RenameFolderRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+ public virtual List> EmptyFolder(EmptyFolderRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+ public virtual List> MarkFolderAsRead(MarkFolderAsReadRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
+
///
/// Downloads a single missing message from synchronizer and saves it to given FileId from IMailItem.
@@ -456,117 +489,35 @@ namespace Wino.Core.Synchronizers
#region Bundle Helpers
- ///
- /// Creates a batched HttpBundle without a response for a collection of MailItem.
- ///
- /// Generated batch request.
- /// An action to get the native request from the MailItem.
- /// Collection of http bundle that contains batch and native request.
- public IEnumerable> CreateBatchedHttpBundleFromGroup(
- IBatchChangeRequest batchChangeRequest,
- Func, TBaseRequest> action)
+ public List> ForEachRequest(IEnumerable requests,
+ Func action)
+ where TWinoRequestType : IRequestBase
{
- if (batchChangeRequest.Items == null) yield break;
+ List> ret = [];
- var groupedItems = batchChangeRequest.Items.Batch((int)BatchModificationSize);
+ foreach (var request in requests)
+ ret.Add(new HttpRequestBundle(action(request), request));
- foreach (var group in groupedItems)
- yield return new HttpRequestBundle(action(group), batchChangeRequest);
+ return ret;
}
- public IEnumerable> CreateBatchedHttpBundle(
- IBatchChangeRequest batchChangeRequest,
- Func action)
+ public List> CreateSingleBundle(Func action, IRequestBase request, IUIChangeRequest uIChangeRequest)
{
- if (batchChangeRequest.Items == null) yield break;
-
- var groupedItems = batchChangeRequest.Items.Batch((int)BatchModificationSize);
-
- foreach (var group in groupedItems)
- foreach (var item in group)
- yield return new HttpRequestBundle(action(item), item);
-
- yield break;
+ return [new ImapRequestBundle(new ImapRequest(action, request), request, uIChangeRequest)];
}
- ///
- /// Creates a single HttpBundle without a response for a collection of MailItem.
- ///
- /// Batch request
- /// An action to get the native request from the MailItem
- /// Collection of http bundle that contains batch and native request.
- public IEnumerable> CreateHttpBundle(
- IBatchChangeRequest batchChangeRequest,
- Func action)
+ public List> CreateTaskBundle(Func value,
+ List requests)
+ where TSingeRequestType : IRequestBase, IUIChangeRequest
{
- if (batchChangeRequest.Items == null) yield break;
+ List> ret = [];
- foreach (var item in batchChangeRequest.Items)
- yield return new HttpRequestBundle(action(item), batchChangeRequest);
- }
+ foreach (var request in requests)
+ {
+ ret.Add(new ImapRequestBundle(new ImapRequest(value, request), request, request));
+ }
- public IEnumerable> CreateHttpBundle(
- IBatchChangeRequest batchChangeRequest,
- Func action)
- {
- if (batchChangeRequest.Items == null) yield break;
-
- foreach (var item in batchChangeRequest.Items)
- yield return new HttpRequestBundle(action(item), item);
- }
-
- ///
- /// Creates HttpBundle with TResponse of expected response type from the http call for each of the items in the batch.
- ///
- /// Expected http response type after the call.
- /// Generated batch request.
- /// An action to get the native request from the MailItem.
- /// Collection of http bundle that contains batch and native request.
- public IEnumerable> CreateHttpBundleWithResponse(
- IBatchChangeRequest batchChangeRequest,
- Func action)
- {
- if (batchChangeRequest.Items == null) yield break;
-
- foreach (var item in batchChangeRequest.Items)
- yield return new HttpRequestBundle(action(item), batchChangeRequest);
- }
-
- public IEnumerable> CreateHttpBundleWithResponse(
- IRequestBase item,
- Func action)
- {
- yield return new HttpRequestBundle(action(item), item);
- }
-
- ///
- /// Creates a batched HttpBundle with TResponse of expected response type from the http call for each of the items in the batch.
- /// Func will be executed for each item separately in the batch request.
- ///
- /// Expected http response type after the call.
- /// Generated batch request.
- /// An action to get the native request from the MailItem.
- /// Collection of http bundle that contains batch and native request.
- public IEnumerable> CreateBatchedHttpBundle(
- IBatchChangeRequest batchChangeRequest,
- Func action)
- {
- if (batchChangeRequest.Items == null) yield break;
-
- var groupedItems = batchChangeRequest.Items.Batch((int)BatchModificationSize);
-
- foreach (var group in groupedItems)
- foreach (var item in group)
- yield return new HttpRequestBundle(action(item), item);
-
- yield break;
- }
-
- public IEnumerable> CreateTaskBundle(Func value, IRequestBase request)
- {
- var imapreq = new ImapRequest(value, request);
-
- return [new ImapRequestBundle(imapreq, request)];
+ return ret;
}
#endregion
diff --git a/Wino.Core/Synchronizers/Mail/GmailSynchronizer.cs b/Wino.Core/Synchronizers/Mail/GmailSynchronizer.cs
index 15a8966f..c2b79aa7 100644
--- a/Wino.Core/Synchronizers/Mail/GmailSynchronizer.cs
+++ b/Wino.Core/Synchronizers/Mail/GmailSynchronizer.cs
@@ -27,8 +27,9 @@ using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Extensions;
using Wino.Core.Http;
using Wino.Core.Integration.Processors;
-using Wino.Core.Requests;
using Wino.Core.Requests.Bundles;
+using Wino.Core.Requests.Folder;
+using Wino.Core.Requests.Mail;
using Wino.Messaging.UI;
namespace Wino.Core.Synchronizers.Mail
@@ -596,151 +597,148 @@ namespace Wino.Core.Synchronizers.Mail
#region Mail Integrations
- public override IEnumerable> Move(BatchMoveRequest request)
+ public override List> Move(BatchMoveRequest request)
{
- return CreateBatchedHttpBundleFromGroup(request, (items) =>
+ var toFolder = request[0].ToFolder;
+ var fromFolder = request[0].FromFolder;
+
+ // Sent label can't be removed from mails for Gmail.
+ // They are automatically assigned by Gmail.
+ // When you delete sent mail from gmail web portal, it's moved to Trash
+ // but still has Sent label. It's just hidden from the user.
+ // Proper assignments will be done later on CreateAssignment call to mimic this behavior.
+
+ var batchModifyRequest = new BatchModifyMessagesRequest
{
- // Sent label can't be removed from mails for Gmail.
- // They are automatically assigned by Gmail.
- // When you delete sent mail from gmail web portal, it's moved to Trash
- // but still has Sent label. It's just hidden from the user.
- // Proper assignments will be done later on CreateAssignment call to mimic this behavior.
- var batchModifyRequest = new BatchModifyMessagesRequest
- {
- Ids = items.Select(a => a.Item.Id.ToString()).ToList(),
- AddLabelIds = [request.ToFolder.RemoteFolderId]
- };
+ Ids = request.Select(a => a.Item.Id.ToString()).ToList(),
+ AddLabelIds = [toFolder.RemoteFolderId]
+ };
- // Only add remove label ids if the source folder is not sent folder.
- if (request.FromFolder.SpecialFolderType != SpecialFolderType.Sent)
- {
- batchModifyRequest.RemoveLabelIds = [request.FromFolder.RemoteFolderId];
- }
+ // Only add remove label ids if the source folder is not sent folder.
+ if (fromFolder.SpecialFolderType != SpecialFolderType.Sent)
+ {
+ batchModifyRequest.RemoveLabelIds = [fromFolder.RemoteFolderId];
+ }
- return _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
- });
+ var networkCall = _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
+
+ return [new HttpRequestBundle(networkCall, request)];
}
- public override IEnumerable> ChangeFlag(BatchChangeFlagRequest request)
+ public override List> ChangeFlag(BatchChangeFlagRequest request)
{
- return CreateBatchedHttpBundleFromGroup(request, (items) =>
+ bool isFlagged = request[0].IsFlagged;
+
+ var batchModifyRequest = new BatchModifyMessagesRequest
{
- var batchModifyRequest = new BatchModifyMessagesRequest
- {
- Ids = items.Select(a => a.Item.Id.ToString()).ToList(),
- };
+ Ids = request.Select(a => a.Item.Id.ToString()).ToList(),
+ };
- if (request.IsFlagged)
- batchModifyRequest.AddLabelIds = new List() { GoogleIntegratorExtensions.STARRED_LABEL_ID };
- else
- batchModifyRequest.RemoveLabelIds = new List() { GoogleIntegratorExtensions.STARRED_LABEL_ID };
+ if (isFlagged)
+ batchModifyRequest.AddLabelIds = new List() { GoogleIntegratorExtensions.STARRED_LABEL_ID };
+ else
+ batchModifyRequest.RemoveLabelIds = new List() { GoogleIntegratorExtensions.STARRED_LABEL_ID };
- return _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
- });
+ var networkCall = _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
+
+ return [new HttpRequestBundle(networkCall, request)];
}
- public override IEnumerable> MarkRead(BatchMarkReadRequest request)
+ public override List> MarkRead(BatchMarkReadRequest request)
{
- return CreateBatchedHttpBundleFromGroup(request, (items) =>
+ bool readStatus = request[0].IsRead;
+
+ var batchModifyRequest = new BatchModifyMessagesRequest
{
- var batchModifyRequest = new BatchModifyMessagesRequest
- {
- Ids = items.Select(a => a.Item.Id.ToString()).ToList(),
- };
+ Ids = request.Select(a => a.Item.Id.ToString()).ToList(),
+ };
- if (request.IsRead)
- batchModifyRequest.RemoveLabelIds = new List() { GoogleIntegratorExtensions.UNREAD_LABEL_ID };
- else
- batchModifyRequest.AddLabelIds = new List() { GoogleIntegratorExtensions.UNREAD_LABEL_ID };
+ if (readStatus)
+ batchModifyRequest.RemoveLabelIds = new List() { GoogleIntegratorExtensions.UNREAD_LABEL_ID };
+ else
+ batchModifyRequest.AddLabelIds = new List() { GoogleIntegratorExtensions.UNREAD_LABEL_ID };
- return _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
- });
+ var networkCall = _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
+
+ return [new HttpRequestBundle(networkCall, request)];
}
- public override IEnumerable> Delete(BatchDeleteRequest request)
+ public override List> Delete(BatchDeleteRequest request)
{
- return CreateBatchedHttpBundleFromGroup(request, (items) =>
+ var batchModifyRequest = new BatchDeleteMessagesRequest
{
- var batchModifyRequest = new BatchDeleteMessagesRequest
- {
- Ids = items.Select(a => a.Item.Id.ToString()).ToList(),
- };
+ Ids = request.Select(a => a.Item.Id.ToString()).ToList(),
+ };
- return _gmailService.Users.Messages.BatchDelete(batchModifyRequest, "me");
- });
+ var networkCall = _gmailService.Users.Messages.BatchDelete(batchModifyRequest, "me");
+
+ return [new HttpRequestBundle(networkCall, request)];
}
- public override IEnumerable> CreateDraft(BatchCreateDraftRequest request)
+ public override List> CreateDraft(CreateDraftRequest singleRequest)
{
- return CreateHttpBundle(request, (item) =>
- {
- if (item is not CreateDraftRequest singleRequest)
- throw new ArgumentException("BatchCreateDraftRequest collection must be of type CreateDraftRequest.");
+ Draft draft = null;
- Draft draft = null;
+ // It's new mail. Not a reply
+ if (singleRequest.DraftPreperationRequest.ReferenceMailCopy == null)
+ draft = PrepareGmailDraft(singleRequest.DraftPreperationRequest.CreatedLocalDraftMimeMessage);
+ else
+ draft = PrepareGmailDraft(singleRequest.DraftPreperationRequest.CreatedLocalDraftMimeMessage,
+ singleRequest.DraftPreperationRequest.ReferenceMailCopy.ThreadId,
+ singleRequest.DraftPreperationRequest.ReferenceMailCopy.DraftId);
- // It's new mail. Not a reply
- if (singleRequest.DraftPreperationRequest.ReferenceMailCopy == null)
- draft = PrepareGmailDraft(singleRequest.DraftPreperationRequest.CreatedLocalDraftMimeMessage);
- else
- draft = PrepareGmailDraft(singleRequest.DraftPreperationRequest.CreatedLocalDraftMimeMessage,
- singleRequest.DraftPreperationRequest.ReferenceMailCopy.ThreadId,
- singleRequest.DraftPreperationRequest.ReferenceMailCopy.DraftId);
+ var networkCall = _gmailService.Users.Drafts.Create(draft, "me");
- return _gmailService.Users.Drafts.Create(draft, "me");
- });
+ return [new HttpRequestBundle(networkCall, singleRequest, singleRequest)];
}
- public override IEnumerable> Archive(BatchArchiveRequest request)
+ public override List> Archive(BatchArchiveRequest request)
{
- return CreateBatchedHttpBundleFromGroup(request, (items) =>
+ bool isArchiving = request[0].IsArchiving;
+ var batchModifyRequest = new BatchModifyMessagesRequest
{
- var batchModifyRequest = new BatchModifyMessagesRequest
- {
- Ids = items.Select(a => a.Item.Id.ToString()).ToList()
- };
+ Ids = request.Select(a => a.Item.Id.ToString()).ToList()
+ };
- if (request.IsArchiving)
- {
- batchModifyRequest.RemoveLabelIds = new[] { GoogleIntegratorExtensions.INBOX_LABEL_ID };
- }
- else
- {
- batchModifyRequest.AddLabelIds = new[] { GoogleIntegratorExtensions.INBOX_LABEL_ID };
- }
+ if (isArchiving)
+ {
+ batchModifyRequest.RemoveLabelIds = new[] { GoogleIntegratorExtensions.INBOX_LABEL_ID };
+ }
+ else
+ {
+ batchModifyRequest.AddLabelIds = new[] { GoogleIntegratorExtensions.INBOX_LABEL_ID };
+ }
- return _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
- });
+ var networkCall = _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
+
+ return [new HttpRequestBundle(networkCall, request)];
}
- public override IEnumerable> SendDraft(BatchSendDraftRequestRequest request)
+ public override List> SendDraft(SendDraftRequest singleDraftRequest)
{
- return CreateHttpBundle(request, (item) =>
+
+ var message = new Message();
+
+ if (!string.IsNullOrEmpty(singleDraftRequest.Item.ThreadId))
{
- if (item is not SendDraftRequest singleDraftRequest)
- throw new ArgumentException("BatchSendDraftRequestRequest collection must be of type SendDraftRequest.");
+ message.ThreadId = singleDraftRequest.Item.ThreadId;
+ }
- var message = new Message();
+ singleDraftRequest.Request.Mime.Prepare(EncodingConstraint.None);
- if (!string.IsNullOrEmpty(singleDraftRequest.Item.ThreadId))
- {
- message.ThreadId = singleDraftRequest.Item.ThreadId;
- }
+ var mimeString = singleDraftRequest.Request.Mime.ToString();
+ var base64UrlEncodedMime = Base64UrlEncoder.Encode(mimeString);
+ message.Raw = base64UrlEncodedMime;
- singleDraftRequest.Request.Mime.Prepare(EncodingConstraint.None);
+ var draft = new Draft()
+ {
+ Id = singleDraftRequest.Request.MailItem.DraftId,
+ Message = message
+ };
- var mimeString = singleDraftRequest.Request.Mime.ToString();
- var base64UrlEncodedMime = Base64UrlEncoder.Encode(mimeString);
- message.Raw = base64UrlEncodedMime;
+ var networkCall = _gmailService.Users.Drafts.Send(draft, "me");
- var draft = new Draft()
- {
- Id = singleDraftRequest.Request.MailItem.DraftId,
- Message = message
- };
-
- return _gmailService.Users.Drafts.Send(draft, "me");
- });
+ return [new HttpRequestBundle(networkCall, singleDraftRequest, singleDraftRequest)];
}
public override async Task DownloadMissingMimeMessageAsync(IMailItem mailItem,
@@ -762,23 +760,19 @@ namespace Wino.Core.Synchronizers.Mail
await _gmailChangeProcessor.SaveMimeFileAsync(mailItem.FileId, mimeMessage, Account.Id).ConfigureAwait(false);
}
- public override IEnumerable> RenameFolder(RenameFolderRequest request)
+ public override List> RenameFolder(RenameFolderRequest request)
{
- return CreateHttpBundleWithResponse