Make core library aot compatible.
This commit is contained in:
@@ -253,7 +253,7 @@ public class GmailChangeProcessor : DefaultChangeProcessor, IGmailChangeProcesso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Upsert the event.
|
// Upsert the event.
|
||||||
await Connection.InsertOrReplaceAsync(existingCalendarItem);
|
await Connection.InsertOrReplaceAsync(existingCalendarItem, typeof(CalendarItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetOrganizerName(Event calendarEvent, MailAccount account)
|
private string GetOrganizerName(Event calendarEvent, MailAccount account)
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ public class OutlookChangeProcessor(IDatabaseService databaseService,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Upsert the event.
|
// Upsert the event.
|
||||||
await Connection.InsertOrReplaceAsync(savingItem);
|
await Connection.InsertOrReplaceAsync(savingItem, typeof(CalendarItem));
|
||||||
|
|
||||||
// Manage attendees.
|
// Manage attendees.
|
||||||
if (calendarEvent.Attendees != null)
|
if (calendarEvent.Attendees != null)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization.Metadata;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Interfaces;
|
||||||
@@ -21,12 +21,10 @@ public record HttpRequestBundle<TRequest>(TRequest NativeRequest, IUIChangeReque
|
|||||||
/// <param name="BatchRequest">Batch request that is generated by base synchronizer.</param>
|
/// <param name="BatchRequest">Batch request that is generated by base synchronizer.</param>
|
||||||
public record HttpRequestBundle<TRequest, TResponse>(TRequest NativeRequest, IRequestBase Request) : HttpRequestBundle<TRequest>(NativeRequest, Request)
|
public record HttpRequestBundle<TRequest, TResponse>(TRequest NativeRequest, IRequestBase Request) : HttpRequestBundle<TRequest>(NativeRequest, Request)
|
||||||
{
|
{
|
||||||
[RequiresDynamicCode("AOT")]
|
public async Task<TResponse> DeserializeBundleAsync(HttpResponseMessage httpResponse, JsonTypeInfo<TResponse> typeInfo, CancellationToken cancellationToken = default)
|
||||||
[RequiresUnreferencedCode("AOT")]
|
|
||||||
public async Task<TResponse> DeserializeBundleAsync(HttpResponseMessage httpResponse, CancellationToken cancellationToken = default)
|
|
||||||
{
|
{
|
||||||
var content = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
|
var content = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
return JsonSerializer.Deserialize<TResponse>(content) ?? throw new InvalidOperationException("Invalid Http Response Deserialization");
|
return JsonSerializer.Deserialize(content, typeInfo) ?? throw new InvalidOperationException("Invalid Http Response Deserialization");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
@@ -42,6 +43,11 @@ using CalendarService = Google.Apis.Calendar.v3.CalendarService;
|
|||||||
|
|
||||||
namespace Wino.Core.Synchronizers.Mail;
|
namespace Wino.Core.Synchronizers.Mail;
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(Message))]
|
||||||
|
[JsonSerializable(typeof(Label))]
|
||||||
|
[JsonSerializable(typeof(Draft))]
|
||||||
|
public partial class GmailSynchronizerJsonContext : JsonSerializerContext;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gmail synchronizer implementation with per-folder history ID synchronization.
|
/// Gmail synchronizer implementation with per-folder history ID synchronization.
|
||||||
///
|
///
|
||||||
@@ -190,7 +196,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
|||||||
|
|
||||||
// Get all folders to synchronize
|
// Get all folders to synchronize
|
||||||
var synchronizationFolders = await _gmailChangeProcessor.GetSynchronizationFoldersAsync(options).ConfigureAwait(false);
|
var synchronizationFolders = await _gmailChangeProcessor.GetSynchronizationFoldersAsync(options).ConfigureAwait(false);
|
||||||
|
|
||||||
_logger.Information("Synchronizing {Count} folders for {Name}", synchronizationFolders.Count, Account.Name);
|
_logger.Information("Synchronizing {Count} folders for {Name}", synchronizationFolders.Count, Account.Name);
|
||||||
|
|
||||||
var totalFolders = synchronizationFolders.Count;
|
var totalFolders = synchronizationFolders.Count;
|
||||||
@@ -1132,12 +1138,12 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
MimeMessage mimeMessage = null;
|
MimeMessage mimeMessage = null;
|
||||||
|
|
||||||
// Extract MIME if we downloaded raw format
|
// Extract MIME if we downloaded raw format
|
||||||
if (downloadRawMime)
|
if (downloadRawMime)
|
||||||
{
|
{
|
||||||
mimeMessage = gmailMessage.GetGmailMimeMessage();
|
mimeMessage = gmailMessage.GetGmailMimeMessage();
|
||||||
|
|
||||||
if (mimeMessage == null)
|
if (mimeMessage == null)
|
||||||
{
|
{
|
||||||
_logger.Warning("Failed to parse MIME for message {MessageId}", gmailMessage.Id);
|
_logger.Warning("Failed to parse MIME for message {MessageId}", gmailMessage.Id);
|
||||||
@@ -1152,17 +1158,17 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
|||||||
// For Gmail, multiple packages can share the same message (different labels/folders)
|
// For Gmail, multiple packages can share the same message (different labels/folders)
|
||||||
// They should all share the same FileId so MIME is stored only once
|
// They should all share the same FileId so MIME is stored only once
|
||||||
Guid sharedFileId = Guid.NewGuid();
|
Guid sharedFileId = Guid.NewGuid();
|
||||||
|
|
||||||
foreach (var package in packages)
|
foreach (var package in packages)
|
||||||
{
|
{
|
||||||
// Set the same FileId for all copies
|
// Set the same FileId for all copies
|
||||||
package.Copy.FileId = sharedFileId;
|
package.Copy.FileId = sharedFileId;
|
||||||
|
|
||||||
// Create the mail copy with the MIME (if downloaded)
|
// Create the mail copy with the MIME (if downloaded)
|
||||||
var packageWithMime = downloadRawMime && mimeMessage != null
|
var packageWithMime = downloadRawMime && mimeMessage != null
|
||||||
? new NewMailItemPackage(package.Copy, mimeMessage, package.AssignedRemoteFolderId)
|
? new NewMailItemPackage(package.Copy, mimeMessage, package.AssignedRemoteFolderId)
|
||||||
: package;
|
: package;
|
||||||
|
|
||||||
await _gmailChangeProcessor.CreateMailAsync(Account.Id, packageWithMime).ConfigureAwait(false);
|
await _gmailChangeProcessor.CreateMailAsync(Account.Id, packageWithMime).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1367,7 +1373,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
|||||||
|
|
||||||
if (bundle is HttpRequestBundle<IClientServiceRequest, Message> messageBundle)
|
if (bundle is HttpRequestBundle<IClientServiceRequest, Message> messageBundle)
|
||||||
{
|
{
|
||||||
var gmailMessage = await messageBundle.DeserializeBundleAsync(httpResponseMessage, cancellationToken).ConfigureAwait(false);
|
var gmailMessage = await messageBundle.DeserializeBundleAsync(httpResponseMessage, GmailSynchronizerJsonContext.Default.Message, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (gmailMessage == null) return;
|
if (gmailMessage == null) return;
|
||||||
|
|
||||||
@@ -1392,7 +1398,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
|||||||
{
|
{
|
||||||
// New draft mail is created.
|
// New draft mail is created.
|
||||||
|
|
||||||
var messageDraft = await draftBundle.DeserializeBundleAsync(httpResponseMessage, cancellationToken).ConfigureAwait(false);
|
var messageDraft = await draftBundle.DeserializeBundleAsync(httpResponseMessage, GmailSynchronizerJsonContext.Default.Draft, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (messageDraft == null) return;
|
if (messageDraft == null) return;
|
||||||
|
|
||||||
|
|||||||
@@ -137,7 +137,6 @@ public abstract class ImapSynchronizationStrategyBase : IImapSynchronizerStrateg
|
|||||||
|
|
||||||
foreach (var uniqueId in uniqueIds)
|
foreach (var uniqueId in uniqueIds)
|
||||||
{
|
{
|
||||||
if (uniqueId == null) continue;
|
|
||||||
var localMailCopyId = MailkitClientExtensions.CreateUid(Folder.Id, uniqueId.Id);
|
var localMailCopyId = MailkitClientExtensions.CreateUid(Folder.Id, uniqueId.Id);
|
||||||
|
|
||||||
await MailService.DeleteMailAsync(Folder.MailAccountId, localMailCopyId).ConfigureAwait(false);
|
await MailService.DeleteMailAsync(Folder.MailAccountId, localMailCopyId).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -34,10 +34,11 @@ namespace Wino.Core.Synchronizers.Mail;
|
|||||||
|
|
||||||
public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreationPackage, object>, IImapSynchronizer
|
public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreationPackage, object>, IImapSynchronizer
|
||||||
{
|
{
|
||||||
[Obsolete("N/A")]
|
/// <summary>
|
||||||
|
/// N/A for IMAP as it doesn't support batch modifications natively.
|
||||||
|
/// </summary>
|
||||||
public override uint BatchModificationSize => 1000;
|
public override uint BatchModificationSize => 1000;
|
||||||
public override uint InitialMessageDownloadCountPerFolder => 500;
|
public override uint InitialMessageDownloadCountPerFolder => 500;
|
||||||
public override int InitialSyncMimeDownloadCount => 50;
|
|
||||||
|
|
||||||
#region Idle Implementation
|
#region Idle Implementation
|
||||||
|
|
||||||
@@ -313,7 +314,7 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
|
|||||||
for (int i = 0; i < totalFolders; i++)
|
for (int i = 0; i < totalFolders; i++)
|
||||||
{
|
{
|
||||||
var folder = synchronizationFolders[i];
|
var folder = synchronizationFolders[i];
|
||||||
|
|
||||||
// Update progress based on folder completion
|
// Update progress based on folder completion
|
||||||
UpdateSyncProgress(totalFolders, totalFolders - (i + 1), $"Syncing {folder.FolderName}...");
|
UpdateSyncProgress(totalFolders, totalFolders - (i + 1), $"Syncing {folder.FolderName}...");
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
@@ -574,23 +573,23 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
|||||||
{
|
{
|
||||||
// This message belongs to existing local draft copy.
|
// This message belongs to existing local draft copy.
|
||||||
// We don't need to create a new mail copy for this message, just update the existing one.
|
// We don't need to create a new mail copy for this message, just update the existing one.
|
||||||
|
|
||||||
bool isMappingSuccessful = await _outlookChangeProcessor.MapLocalDraftAsync(
|
bool isMappingSuccessful = await _outlookChangeProcessor.MapLocalDraftAsync(
|
||||||
Account.Id,
|
Account.Id,
|
||||||
localDraftCopyUniqueId,
|
localDraftCopyUniqueId,
|
||||||
mailCopy.Id,
|
mailCopy.Id,
|
||||||
mailCopy.DraftId,
|
mailCopy.DraftId,
|
||||||
mailCopy.ThreadId);
|
mailCopy.ThreadId);
|
||||||
|
|
||||||
if (isMappingSuccessful)
|
if (isMappingSuccessful)
|
||||||
{
|
{
|
||||||
_logger.Debug("Successfully mapped remote draft {RemoteId} to local draft {LocalId}",
|
_logger.Debug("Successfully mapped remote draft {RemoteId} to local draft {LocalId}",
|
||||||
mailCopy.Id, localDraftCopyUniqueId);
|
mailCopy.Id, localDraftCopyUniqueId);
|
||||||
return null; // Don't create new mail copy, existing one was updated
|
return null; // Don't create new mail copy, existing one was updated
|
||||||
}
|
}
|
||||||
|
|
||||||
// Local copy doesn't exist. Continue execution to insert mail copy.
|
// Local copy doesn't exist. Continue execution to insert mail copy.
|
||||||
_logger.Debug("Local draft copy {LocalId} not found, creating new mail copy for {RemoteId}",
|
_logger.Debug("Local draft copy {LocalId} not found, creating new mail copy for {RemoteId}",
|
||||||
localDraftCopyUniqueId, mailCopy.Id);
|
localDraftCopyUniqueId, mailCopy.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -875,7 +874,6 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
|||||||
await UpdateDeltaSynchronizationIdentifierAsync(iterator.Deltalink).ConfigureAwait(false);
|
await UpdateDeltaSynchronizationIdentifierAsync(iterator.Deltalink).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[RequiresUnreferencedCode("Calls Microsoft.Kiota.Abstractions.Serialization.KiotaJsonSerializer.DeserializeAsync<T>(String, CancellationToken)")]
|
|
||||||
private async Task<T> DeserializeGraphBatchResponseAsync<T>(BatchResponseContentCollection collection, string requestId, CancellationToken cancellationToken = default) where T : IParsable, new()
|
private async Task<T> DeserializeGraphBatchResponseAsync<T>(BatchResponseContentCollection collection, string requestId, CancellationToken cancellationToken = default) where T : IParsable, new()
|
||||||
{
|
{
|
||||||
// This deserialization may throw generalException in case of failure.
|
// This deserialization may throw generalException in case of failure.
|
||||||
@@ -893,12 +891,12 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
|||||||
}
|
}
|
||||||
catch (ServiceException serviceException)
|
catch (ServiceException serviceException)
|
||||||
{
|
{
|
||||||
|
// TODO: AOT Comaptible inner exception deserialization.
|
||||||
|
|
||||||
// Actual exception is hidden inside ServiceException.
|
// Actual exception is hidden inside ServiceException.
|
||||||
|
// ODataError errorResult = await KiotaJsonSerializer.DeserializeAsync<ODataError>(serviceException.RawResponseBody, cancellationToken);
|
||||||
|
|
||||||
|
throw new SynchronizerException("Outlook Error", serviceException);
|
||||||
ODataError errorResult = await KiotaJsonSerializer.DeserializeAsync<ODataError>(serviceException.RawResponseBody, cancellationToken);
|
|
||||||
|
|
||||||
throw new SynchronizerException("Outlook Error", errorResult);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,14 +45,6 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract uint InitialMessageDownloadCountPerFolder { get; }
|
public abstract uint InitialMessageDownloadCountPerFolder { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// DEPRECATED: MIME messages are no longer downloaded during synchronization.
|
|
||||||
/// MIME content is only downloaded when explicitly needed (e.g., when user reads a message).
|
|
||||||
/// This property is kept for backward compatibility but is no longer used.
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete("MIME messages are no longer downloaded during sync. Use DownloadMissingMimeMessageAsync instead.")]
|
|
||||||
public virtual int InitialSyncMimeDownloadCount => 0;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new Wino Mail Item package out of native message type with metadata only.
|
/// Creates a new Wino Mail Item package out of native message type with metadata only.
|
||||||
/// NO MIME content is downloaded during synchronization - only headers and essential metadata.
|
/// NO MIME content is downloaded during synchronization - only headers and essential metadata.
|
||||||
|
|||||||
Reference in New Issue
Block a user