Merge branch 'main' into hotfix/Expander

This commit is contained in:
Burak Kaan Köse
2024-08-30 01:11:19 +02:00
36 changed files with 430 additions and 560 deletions

View File

@@ -1,11 +0,0 @@
namespace Wino.Core.Domain.Enums
{
public enum EditorToolbarSectionType
{
None,
Format,
Insert,
Draw,
Options
}
}

View File

@@ -1,8 +0,0 @@
namespace Wino.Core.Domain.Enums
{
public enum MenuPaneMode
{
Visible,
Hidden
}
}

View File

@@ -9,7 +9,6 @@ namespace Wino.Core.Domain.Interfaces
public interface IThemeService : IInitializeAsync public interface IThemeService : IInitializeAsync
{ {
event EventHandler<ApplicationElementTheme> ElementThemeChanged; event EventHandler<ApplicationElementTheme> ElementThemeChanged;
event EventHandler<string> AccentColorChangedBySystem;
event EventHandler<string> AccentColorChanged; event EventHandler<string> AccentColorChanged;
Task<List<AppThemeBase>> GetAvailableThemesAsync(); Task<List<AppThemeBase>> GetAvailableThemesAsync();

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Wino.Core.Domain.Entities; using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
namespace Wino.Core.Domain.Interfaces namespace Wino.Core.Domain.Interfaces
@@ -12,7 +13,7 @@ namespace Wino.Core.Domain.Interfaces
/// </summary> /// </summary>
/// <param name="items">Original mails.</param> /// <param name="items">Original mails.</param>
/// <returns>Original mails with thread mails.</returns> /// <returns>Original mails with thread mails.</returns>
Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items); Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items, IMailItemFolder threadingForFolder);
bool ShouldThreadWithItem(IMailItem originalItem, IMailItem targetItem); bool ShouldThreadWithItem(IMailItem originalItem, IMailItem targetItem);
} }
} }

View File

@@ -14,19 +14,19 @@ namespace Wino.Core.Domain.Models.MailItem
public IMailItem LatestMailItem => ThreadItems.LastOrDefault(); public IMailItem LatestMailItem => ThreadItems.LastOrDefault();
public IMailItem FirstMailItem => ThreadItems.FirstOrDefault(); public IMailItem FirstMailItem => ThreadItems.FirstOrDefault();
public void AddThreadItem(IMailItem item) public bool AddThreadItem(IMailItem item)
{ {
if (item == null) return; if (item == null) return false;
if (ThreadItems.Any(a => a.Id == item.Id)) if (ThreadItems.Any(a => a.Id == item.Id))
{ {
return; return false;
} }
if (item != null && item.IsDraft) if (item != null && item.IsDraft)
{ {
ThreadItems.Insert(0, item); ThreadItems.Insert(0, item);
return; return true;
} }
var insertItem = ThreadItems.FirstOrDefault(a => !a.IsDraft && a.CreationDate < item.CreationDate); var insertItem = ThreadItems.FirstOrDefault(a => !a.IsDraft && a.CreationDate < item.CreationDate);
@@ -39,6 +39,8 @@ namespace Wino.Core.Domain.Models.MailItem
ThreadItems.Insert(index, item); ThreadItems.Insert(index, item);
} }
return true;
} }
public IEnumerable<Guid> GetContainingIds() => ThreadItems?.Select(a => a.UniqueId) ?? default; public IEnumerable<Guid> GetContainingIds() => ThreadItems?.Select(a => a.UniqueId) ?? default;

View File

@@ -1,30 +0,0 @@
using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Models.Reader
{
public class EditorToolbarSection
{
public EditorToolbarSectionType SectionType { get; set; }
public string Title
{
get
{
switch (SectionType)
{
case EditorToolbarSectionType.None:
return Translator.EditorToolbarOption_None;
case EditorToolbarSectionType.Format:
return Translator.EditorToolbarOption_Format;
case EditorToolbarSectionType.Insert:
return Translator.EditorToolbarOption_Insert;
case EditorToolbarSectionType.Draw:
return Translator.EditorToolbarOption_Draw;
case EditorToolbarSectionType.Options:
return Translator.EditorToolbarOption_Options;
default:
return "Unknown Editor Option";
}
}
}
}
}

View File

@@ -53,6 +53,7 @@
"Buttons_TryAgain": "Try Again", "Buttons_TryAgain": "Try Again",
"Buttons_Yes": "Yes", "Buttons_Yes": "Yes",
"Buttons_Reset": "Reset", "Buttons_Reset": "Reset",
"Buttons_Send": "Send",
"Center": "Center", "Center": "Center",
"ComingSoon": "Coming soon...", "ComingSoon": "Coming soon...",
"ComposerFrom": "From: ", "ComposerFrom": "From: ",

View File

@@ -288,6 +288,11 @@ namespace Wino.Core.Domain
/// </summary> /// </summary>
public static string Buttons_Reset => Resources.GetTranslatedString(@"Buttons_Reset"); public static string Buttons_Reset => Resources.GetTranslatedString(@"Buttons_Reset");
/// <summary>
/// Send
/// </summary>
public static string Buttons_Send => Resources.GetTranslatedString(@"Buttons_Send");
/// <summary> /// <summary>
/// Center /// Center
/// </summary> /// </summary>

View File

@@ -62,7 +62,7 @@
</PackageReference> </PackageReference>
<PackageReference Include="MimeKit" Version="4.7.1" /> <PackageReference Include="MimeKit" Version="4.7.1" />
<PackageReference Include="MailKit" Version="4.7.1.1" /> <PackageReference Include="MailKit" Version="4.7.1.1" />
<PackageReference Include="sqlite-net-pcl" Version="1.8.116" /> <PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
<PackageReference Include="System.Text.Json" Version="8.0.4" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -46,7 +46,6 @@ namespace Wino.Services
public event EventHandler<ApplicationElementTheme> ElementThemeChanged; public event EventHandler<ApplicationElementTheme> ElementThemeChanged;
public event EventHandler<string> AccentColorChanged; public event EventHandler<string> AccentColorChanged;
public event EventHandler<string> AccentColorChangedBySystem;
private const string AccentColorKey = nameof(AccentColorKey); private const string AccentColorKey = nameof(AccentColorKey);
private const string CurrentApplicationThemeKey = nameof(CurrentApplicationThemeKey); private const string CurrentApplicationThemeKey = nameof(CurrentApplicationThemeKey);

View File

@@ -112,7 +112,7 @@
<Version>7.1.2</Version> <Version>7.1.2</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.AppCenter.Analytics"> <PackageReference Include="Microsoft.AppCenter.Analytics">
<Version>5.0.4</Version> <Version>5.0.5</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform"> <PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.2.14</Version> <Version>6.2.14</Version>

View File

@@ -26,8 +26,6 @@ namespace Wino.Core.Authenticators
private readonly INativeAppService _nativeAppService; private readonly INativeAppService _nativeAppService;
public event EventHandler<string> InteractiveAuthenticationRequired;
public GmailAuthenticator(ITokenService tokenService, INativeAppService nativeAppService) : base(tokenService) public GmailAuthenticator(ITokenService tokenService, INativeAppService nativeAppService) : base(tokenService)
{ {
_nativeAppService = nativeAppService; _nativeAppService = nativeAppService;

View File

@@ -28,7 +28,16 @@ namespace Wino.Core.Authenticators
public string ClientId { get; } = "b19c2035-d740-49ff-b297-de6ec561b208"; public string ClientId { get; } = "b19c2035-d740-49ff-b297-de6ec561b208";
private readonly string[] MailScope = ["email", "mail.readwrite", "offline_access", "mail.send", "Mail.Send.Shared", "Mail.ReadWrite.Shared"]; private readonly string[] MailScope =
[
"email",
"mail.readwrite",
"offline_access",
"mail.send",
"Mail.Send.Shared",
"Mail.ReadWrite.Shared",
"User.Read"
];
public override MailProviderType ProviderType => MailProviderType.Outlook; public override MailProviderType ProviderType => MailProviderType.Outlook;

View File

@@ -180,7 +180,7 @@ namespace Wino.Core.Extensions
// Some headers also require to start with X- or x-. // Some headers also require to start with X- or x-.
string[] headersToIgnore = ["Date", "To", "MIME-Version", "From", "Subject", "Message-Id"]; string[] headersToIgnore = ["Date", "To", "Cc", "Bcc", "MIME-Version", "From", "Subject", "Message-Id"];
string[] headersToModify = ["In-Reply-To", "Reply-To", "References", "Thread-Topic"]; string[] headersToModify = ["In-Reply-To", "Reply-To", "References", "Thread-Topic"];
var headers = new List<InternetMessageHeader>(); var headers = new List<InternetMessageHeader>();
@@ -191,15 +191,12 @@ namespace Wino.Core.Extensions
{ {
if (!headersToIgnore.Contains(header.Field)) if (!headersToIgnore.Contains(header.Field))
{ {
if (headersToModify.Contains(header.Field)) var headerName = headersToModify.Contains(header.Field) ? $"X-{header.Field}" : header.Field;
{
headers.Add(new InternetMessageHeader() { Name = $"X-{header.Field}", Value = header.Value });
}
else
{
headers.Add(new InternetMessageHeader() { Name = header.Field, Value = header.Value });
}
// No header value should exceed 995 characters.
var headerValue = header.Value.Length >= 995 ? header.Value.Substring(0, 995) : header.Value;
headers.Add(new InternetMessageHeader() { Name = headerName, Value = headerValue });
includedHeaderCount++; includedHeaderCount++;
} }

View File

@@ -21,7 +21,6 @@ namespace Wino.Core.Integration.Processors
{ {
Task UpdateAccountAsync(MailAccount account); Task UpdateAccountAsync(MailAccount account);
Task<string> UpdateAccountDeltaSynchronizationIdentifierAsync(Guid accountId, string deltaSynchronizationIdentifier); Task<string> UpdateAccountDeltaSynchronizationIdentifierAsync(Guid accountId, string deltaSynchronizationIdentifier);
Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId);
Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId); Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId);
Task ChangeMailReadStatusAsync(string mailCopyId, bool isRead); Task ChangeMailReadStatusAsync(string mailCopyId, bool isRead);
Task ChangeFlagStatusAsync(string mailCopyId, bool isFlagged); Task ChangeFlagStatusAsync(string mailCopyId, bool isFlagged);
@@ -53,6 +52,7 @@ namespace Wino.Core.Integration.Processors
public interface IGmailChangeProcessor : IDefaultChangeProcessor public interface IGmailChangeProcessor : IDefaultChangeProcessor
{ {
Task MapLocalDraftAsync(string mailCopyId, string newDraftId, string newThreadId); Task MapLocalDraftAsync(string mailCopyId, string newDraftId, string newThreadId);
Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId);
} }
public interface IOutlookChangeProcessor : IDefaultChangeProcessor public interface IOutlookChangeProcessor : IDefaultChangeProcessor
@@ -135,8 +135,7 @@ namespace Wino.Core.Integration.Processors
public Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId) public Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId)
=> MailService.DeleteAssignmentAsync(accountId, mailCopyId, remoteFolderId); => MailService.DeleteAssignmentAsync(accountId, mailCopyId, remoteFolderId);
public Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId)
=> MailService.CreateAssignmentAsync(accountId, mailCopyId, remoteFolderId);
public Task DeleteMailAsync(Guid accountId, string mailId) public Task DeleteMailAsync(Guid accountId, string mailId)
=> MailService.DeleteMailAsync(accountId, mailId); => MailService.DeleteMailAsync(accountId, mailId);

View File

@@ -1,4 +1,5 @@
using System.Threading.Tasks; using System;
using System.Threading.Tasks;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Services; using Wino.Core.Services;
@@ -12,5 +13,8 @@ namespace Wino.Core.Integration.Processors
public Task MapLocalDraftAsync(string mailCopyId, string newDraftId, string newThreadId) public Task MapLocalDraftAsync(string mailCopyId, string newDraftId, string newThreadId)
=> MailService.MapLocalDraftAsync(mailCopyId, newDraftId, newThreadId); => MailService.MapLocalDraftAsync(mailCopyId, newDraftId, newThreadId);
public Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId)
=> MailService.CreateAssignmentAsync(accountId, mailCopyId, remoteFolderId);
} }
} }

View File

@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Wino.Core.Domain.Entities; using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Services; using Wino.Core.Services;
@@ -27,7 +28,7 @@ namespace Wino.Core.Integration.Threading
} }
///<inheritdoc/> ///<inheritdoc/>
public async Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items) public async Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items, IMailItemFolder threadingForFolder)
{ {
var assignedAccount = items[0].AssignedAccount; var assignedAccount = items[0].AssignedAccount;
@@ -62,11 +63,43 @@ namespace Wino.Core.Integration.Threading
} }
var thread = new ThreadMailItem(); var thread = new ThreadMailItem();
foreach (var childThreadItem in threadItem) foreach (var childThreadItem in threadItem)
{ {
thread.AddThreadItem(childThreadItem); if (thread.ThreadItems.Any(a => a.Id == childThreadItem.Id))
{
// Mail already exist in the thread.
// There should be only 1 instance of the mail in the thread.
// Make sure we add the correct one.
// Add the one with threading folder.
var threadingFolderItem = threadItem.FirstOrDefault(a => a.Id == childThreadItem.Id && a.FolderId == threadingForFolder.Id);
if (threadingFolderItem == null) continue;
// Remove the existing one.
thread.ThreadItems.Remove(thread.ThreadItems.First(a => a.Id == childThreadItem.Id));
// Add the correct one for listing.
thread.AddThreadItem(threadingFolderItem);
}
else
{
thread.AddThreadItem(childThreadItem);
}
}
if (thread.ThreadItems.Count > 1)
{
resultList.Add(thread);
}
else
{
// Don't make threads if the thread has only one item.
// Gmail has may have multiple assignments for the same item.
resultList.Add(thread.ThreadItems.First());
} }
resultList.Add(thread);
} }
} }

View File

@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using SqlKata; using SqlKata;
using Wino.Core.Domain.Entities; using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Extensions; using Wino.Core.Extensions;
using Wino.Core.Services; using Wino.Core.Services;
@@ -58,7 +59,7 @@ namespace Wino.Core.Integration.Threading
return _databaseService.Connection.FindWithQueryAsync<MailCopy>(query.GetRawQuery()); return _databaseService.Connection.FindWithQueryAsync<MailCopy>(query.GetRawQuery());
} }
public async Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items) public async Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items, IMailItemFolder threadingForFolder)
{ {
var threads = new List<ThreadMailItem>(); var threads = new List<ThreadMailItem>();

View File

@@ -58,7 +58,7 @@ namespace Wino.Core.Requests
Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailAddedMessage(item.Item))); Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailAddedMessage(item.Item)));
} }
public override int ResynchronizationDelay => 10000; public override int ResynchronizationDelay => 6000;
public override bool ExecuteSerialBatch => true; public override bool ExecuteSerialBatch => true;
} }
} }

View File

@@ -241,7 +241,7 @@ namespace Wino.Core.Services
// Only thread items from Draft and Sent folders must present here. // Only thread items from Draft and Sent folders must present here.
// Otherwise this strategy will fetch the items that are in Deleted folder as well. // Otherwise this strategy will fetch the items that are in Deleted folder as well.
var accountThreadedItems = await threadingStrategy.ThreadItemsAsync([.. group]); var accountThreadedItems = await threadingStrategy.ThreadItemsAsync([.. group], options.Folders.First());
// Populate threaded items with folder and account assignments. // Populate threaded items with folder and account assignments.
// Almost everything already should be in cache from initial population. // Almost everything already should be in cache from initial population.
@@ -409,12 +409,11 @@ namespace Wino.Core.Services
foreach (var mailItem in allMails) foreach (var mailItem in allMails)
{ {
await DeleteMailInternalAsync(mailItem).ConfigureAwait(false); // Delete mime file as well.
// Delete mime file.
// Even though Gmail might have multiple copies for the same mail, we only have one MIME file for all. // Even though Gmail might have multiple copies for the same mail, we only have one MIME file for all.
// Their FileId is inserted same. // Their FileId is inserted same.
await _mimeFileService.DeleteMimeMessageAsync(accountId, mailItem.FileId);
await DeleteMailInternalAsync(mailItem, preserveMimeFile: false).ConfigureAwait(false);
} }
} }
@@ -457,7 +456,7 @@ namespace Wino.Core.Services
ReportUIChange(new MailUpdatedMessage(mailCopy)); ReportUIChange(new MailUpdatedMessage(mailCopy));
} }
private async Task DeleteMailInternalAsync(MailCopy mailCopy) private async Task DeleteMailInternalAsync(MailCopy mailCopy, bool preserveMimeFile)
{ {
if (mailCopy == null) if (mailCopy == null)
{ {
@@ -473,7 +472,7 @@ namespace Wino.Core.Services
// If there are no more copies exists of the same mail, delete the MIME file as well. // If there are no more copies exists of the same mail, delete the MIME file as well.
var isMailExists = await IsMailExistsAsync(mailCopy.Id).ConfigureAwait(false); var isMailExists = await IsMailExistsAsync(mailCopy.Id).ConfigureAwait(false);
if (!isMailExists) if (!isMailExists && !preserveMimeFile)
{ {
await _mimeFileService.DeleteMimeMessageAsync(mailCopy.AssignedAccount.Id, mailCopy.FileId).ConfigureAwait(false); await _mimeFileService.DeleteMimeMessageAsync(mailCopy.AssignedAccount.Id, mailCopy.FileId).ConfigureAwait(false);
} }
@@ -554,6 +553,19 @@ namespace Wino.Core.Services
return; return;
} }
if (mailCopy.AssignedFolder.SpecialFolderType == SpecialFolderType.Sent &&
localFolder.SpecialFolderType == SpecialFolderType.Deleted)
{
// Sent item is deleted.
// Gmail does not delete the sent items, but moves them to the deleted folder.
// API doesn't allow removing Sent label.
// Here we intercept this behavior, removing the Sent copy of the mail and adding the Deleted copy.
// This way item will only be visible in Trash folder as in Gmail Web UI.
// Don't delete MIME file since if exists.
await DeleteMailInternalAsync(mailCopy, preserveMimeFile: true).ConfigureAwait(false);
}
// Copy one of the mail copy and assign it to the new folder. // Copy one of the mail copy and assign it to the new folder.
// We don't need to create a new MIME pack. // We don't need to create a new MIME pack.
// Therefore FileId is not changed for the new MailCopy. // Therefore FileId is not changed for the new MailCopy.
@@ -585,7 +597,7 @@ namespace Wino.Core.Services
return; return;
} }
await DeleteMailInternalAsync(mailItem).ConfigureAwait(false); await DeleteMailInternalAsync(mailItem, preserveMimeFile: false).ConfigureAwait(false);
} }
public async Task<bool> CreateMailAsync(Guid accountId, NewMailItemPackage package) public async Task<bool> CreateMailAsync(Guid accountId, NewMailItemPackage package)

View File

@@ -595,13 +595,23 @@ namespace Wino.Core.Synchronizers
{ {
return CreateBatchedHttpBundleFromGroup(request, (items) => return CreateBatchedHttpBundleFromGroup(request, (items) =>
{ {
// 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 var batchModifyRequest = new BatchModifyMessagesRequest
{ {
Ids = items.Select(a => a.Item.Id.ToString()).ToList(), Ids = items.Select(a => a.Item.Id.ToString()).ToList(),
AddLabelIds = new[] { request.ToFolder.RemoteFolderId }, AddLabelIds = [request.ToFolder.RemoteFolderId]
RemoveLabelIds = new[] { request.FromFolder.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];
}
return _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me"); return _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
}); });
} }
@@ -793,6 +803,8 @@ namespace Wino.Core.Synchronizers
var bundleRequestCount = bundle.Count(); var bundleRequestCount = bundle.Count();
var bundleTasks = new List<Task>();
for (int k = 0; k < bundleRequestCount; k++) for (int k = 0; k < bundleRequestCount; k++)
{ {
var requestBundle = bundle.ElementAt(k); var requestBundle = bundle.ElementAt(k);
@@ -802,37 +814,40 @@ namespace Wino.Core.Synchronizers
request.ApplyUIChanges(); request.ApplyUIChanges();
// TODO: Queue is synchronous. Create a task bucket to await all processing. nativeBatchRequest.Queue<object>(nativeRequest, (content, error, index, message)
nativeBatchRequest.Queue<object>(nativeRequest, async (content, error, index, message) => bundleTasks.Add(ProcessSingleNativeRequestResponseAsync(requestBundle, error, message, cancellationToken)));
=> await ProcessSingleNativeRequestResponseAsync(requestBundle, error, message, cancellationToken).ConfigureAwait(false));
} }
await nativeBatchRequest.ExecuteAsync(cancellationToken).ConfigureAwait(false); await nativeBatchRequest.ExecuteAsync(cancellationToken).ConfigureAwait(false);
await Task.WhenAll(bundleTasks);
} }
} }
private void ProcessGmailRequestError(RequestError error) private void ProcessGmailRequestError(RequestError error, IRequestBundle<IClientServiceRequest> bundle)
{ {
if (error == null) return; if (error == null) return;
// OutOfMemoryException is a known bug in Gmail SDK. // OutOfMemoryException is a known bug in Gmail SDK.
if (error.Code == 0) if (error.Code == 0)
{ {
bundle?.Request.RevertUIChanges();
throw new OutOfMemoryException(error.Message); throw new OutOfMemoryException(error.Message);
} }
// Entity not found. // Entity not found.
if (error.Code == 404) if (error.Code == 404)
{ {
bundle?.Request.RevertUIChanges();
throw new SynchronizerEntityNotFoundException(error.Message); throw new SynchronizerEntityNotFoundException(error.Message);
} }
if (!string.IsNullOrEmpty(error.Message)) if (!string.IsNullOrEmpty(error.Message))
{ {
bundle?.Request.RevertUIChanges();
error.Errors?.ForEach(error => _logger.Error("Unknown Gmail SDK error for {Name}\n{Error}", Account.Name, error)); error.Errors?.ForEach(error => _logger.Error("Unknown Gmail SDK error for {Name}\n{Error}", Account.Name, error));
// TODO: Debug throw new SynchronizerException(error.Message);
// throw new SynchronizerException(error.Message);
} }
} }
@@ -851,7 +866,7 @@ namespace Wino.Core.Synchronizers
{ {
try try
{ {
ProcessGmailRequestError(error); ProcessGmailRequestError(error, null);
} }
catch (OutOfMemoryException) catch (OutOfMemoryException)
{ {
@@ -900,7 +915,7 @@ namespace Wino.Core.Synchronizers
HttpResponseMessage httpResponseMessage, HttpResponseMessage httpResponseMessage,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
ProcessGmailRequestError(error); ProcessGmailRequestError(error, bundle);
if (bundle is HttpRequestBundle<IClientServiceRequest, Message> messageBundle) if (bundle is HttpRequestBundle<IClientServiceRequest, Message> messageBundle)
{ {

View File

@@ -12,6 +12,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Graph; using Microsoft.Graph;
using Microsoft.Graph.Models; using Microsoft.Graph.Models;
using Microsoft.Graph.Models.ODataErrors;
using Microsoft.Kiota.Abstractions; using Microsoft.Kiota.Abstractions;
using Microsoft.Kiota.Abstractions.Authentication; using Microsoft.Kiota.Abstractions.Authentication;
using Microsoft.Kiota.Http.HttpClientLibrary.Middleware; using Microsoft.Kiota.Http.HttpClientLibrary.Middleware;
@@ -473,13 +474,27 @@ namespace Wino.Core.Synchronizers
/// <returns>Base64 encoded profile picture.</returns> /// <returns>Base64 encoded profile picture.</returns>
private async Task<string> GetUserProfilePictureAsync() private async Task<string> GetUserProfilePictureAsync()
{ {
var photoStream = await _graphClient.Me.Photos["48x48"].Content.GetAsync(); try
{
var photoStream = await _graphClient.Me.Photos["48x48"].Content.GetAsync();
using var memoryStream = new MemoryStream(); using var memoryStream = new MemoryStream();
await photoStream.CopyToAsync(memoryStream); await photoStream.CopyToAsync(memoryStream);
var byteArray = memoryStream.ToArray(); var byteArray = memoryStream.ToArray();
return Convert.ToBase64String(byteArray); return Convert.ToBase64String(byteArray);
}
catch (ODataError odataError) when (odataError.Error.Code == "ImageNotFound")
{
// Accounts without profile picture will throw this error.
// At this point nothing we can do. Just return empty string.
return string.Empty;
}
catch (Exception)
{
throw;
}
} }
/// <summary> /// <summary>

View File

@@ -18,7 +18,7 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="Google.Apis.Gmail.v1" Version="1.68.0.3427" /> <PackageReference Include="Google.Apis.Gmail.v1" Version="1.68.0.3427" />
<PackageReference Include="Google.Apis.PeopleService.v1" Version="1.68.0.3359" /> <PackageReference Include="Google.Apis.PeopleService.v1" Version="1.68.0.3359" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.63" /> <PackageReference Include="HtmlAgilityPack" Version="1.11.64" />
<PackageReference Include="HtmlKit" Version="1.1.0" /> <PackageReference Include="HtmlKit" Version="1.1.0" />
<PackageReference Include="IsExternalInit" Version="1.0.3"> <PackageReference Include="IsExternalInit" Version="1.0.3">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
@@ -27,16 +27,16 @@
<PackageReference Include="MailKit" Version="4.7.1.1" /> <PackageReference Include="MailKit" Version="4.7.1.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Graph" Version="5.56.0" /> <PackageReference Include="Microsoft.Graph" Version="5.56.0" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.63.0" /> <PackageReference Include="Microsoft.Identity.Client" Version="4.64.0" />
<PackageReference Include="Microsoft.Identity.Client.Broker" Version="4.63.0" /> <PackageReference Include="Microsoft.Identity.Client.Broker" Version="4.64.0" />
<PackageReference Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.63.0" /> <PackageReference Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.64.0" />
<PackageReference Include="MimeKit" Version="4.7.1" /> <PackageReference Include="MimeKit" Version="4.7.1" />
<PackageReference Include="morelinq" Version="4.1.0" /> <PackageReference Include="morelinq" Version="4.3.0" />
<PackageReference Include="Nito.AsyncEx.Tasks" Version="5.1.2" /> <PackageReference Include="Nito.AsyncEx.Tasks" Version="5.1.2" />
<PackageReference Include="Serilog" Version="3.1.1" /> <PackageReference Include="Serilog" Version="4.0.1" />
<PackageReference Include="Serilog.Exceptions" Version="8.4.0" /> <PackageReference Include="Serilog.Exceptions" Version="8.4.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" /> <PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="SkiaSharp" Version="2.88.8" /> <PackageReference Include="SkiaSharp" Version="2.88.8" />
<PackageReference Include="SqlKata" Version="2.4.0" /> <PackageReference Include="SqlKata" Version="2.4.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />

View File

@@ -15,7 +15,6 @@ using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Navigation; using Wino.Core.Domain.Models.Navigation;
using Wino.Core.Domain.Models.Reader;
using Wino.Core.Extensions; using Wino.Core.Extensions;
using Wino.Core.Services; using Wino.Core.Services;
using Wino.Mail.ViewModels.Data; using Wino.Mail.ViewModels.Data;
@@ -89,29 +88,11 @@ namespace Wino.Mail.ViewModels
public ObservableCollection<AccountContact> CCItems { get; set; } = []; public ObservableCollection<AccountContact> CCItems { get; set; } = [];
public ObservableCollection<AccountContact> BCCItems { get; set; } = []; public ObservableCollection<AccountContact> BCCItems { get; set; } = [];
public List<EditorToolbarSection> ToolbarSections { get; set; } =
[
new EditorToolbarSection(){ SectionType = EditorToolbarSectionType.Format },
new EditorToolbarSection(){ SectionType = EditorToolbarSectionType.Insert },
new EditorToolbarSection(){ SectionType = EditorToolbarSectionType.Draw },
new EditorToolbarSection(){ SectionType = EditorToolbarSectionType.Options }
];
private EditorToolbarSection selectedToolbarSection;
public EditorToolbarSection SelectedToolbarSection
{
get => selectedToolbarSection;
set => SetProperty(ref selectedToolbarSection, value);
}
#endregion #endregion
public INativeAppService NativeAppService { get; } public INativeAppService NativeAppService { get; }
private readonly IMailService _mailService; private readonly IMailService _mailService;
private readonly ILaunchProtocolService _launchProtocolService;
private readonly IMimeFileService _mimeFileService; private readonly IMimeFileService _mimeFileService;
private readonly IFolderService _folderService; private readonly IFolderService _folderService;
private readonly IAccountService _accountService; private readonly IAccountService _accountService;
@@ -123,7 +104,6 @@ namespace Wino.Mail.ViewModels
public ComposePageViewModel(IDialogService dialogService, public ComposePageViewModel(IDialogService dialogService,
IMailService mailService, IMailService mailService,
ILaunchProtocolService launchProtocolService,
IMimeFileService mimeFileService, IMimeFileService mimeFileService,
INativeAppService nativeAppService, INativeAppService nativeAppService,
IFolderService folderService, IFolderService folderService,
@@ -141,13 +121,10 @@ namespace Wino.Mail.ViewModels
_folderService = folderService; _folderService = folderService;
_mailService = mailService; _mailService = mailService;
_launchProtocolService = launchProtocolService;
_mimeFileService = mimeFileService; _mimeFileService = mimeFileService;
_accountService = accountService; _accountService = accountService;
_worker = worker; _worker = worker;
_winoServerConnectionManager = winoServerConnectionManager; _winoServerConnectionManager = winoServerConnectionManager;
SelectedToolbarSection = ToolbarSections[0];
} }
[RelayCommand] [RelayCommand]
@@ -263,31 +240,6 @@ namespace Wino.Mail.ViewModels
} }
} }
private void ClearCurrentMimeAttachments()
{
var attachments = new List<MimePart>();
var multiparts = new List<Multipart>();
var iter = new MimeIterator(CurrentMimeMessage);
// collect our list of attachments and their parent multiparts
while (iter.MoveNext())
{
var multipart = iter.Parent as Multipart;
var part = iter.Current as MimePart;
if (multipart != null && part != null && part.IsAttachment)
{
// keep track of each attachment's parent multipart
multiparts.Add(multipart);
attachments.Add(part);
}
}
// now remove each attachment from its parent multipart...
for (int i = 0; i < attachments.Count; i++)
multiparts[i].Remove(attachments[i]);
}
private async Task SaveBodyAsync() private async Task SaveBodyAsync()
{ {
if (GetHTMLBodyFunction != null) if (GetHTMLBodyFunction != null)

View File

@@ -221,21 +221,9 @@ namespace Wino.Mail.ViewModels
_themeService.AccentColorChanged -= AccentColorChanged; _themeService.AccentColorChanged -= AccentColorChanged;
_themeService.ElementThemeChanged -= ElementThemeChanged; _themeService.ElementThemeChanged -= ElementThemeChanged;
_themeService.AccentColorChangedBySystem -= AccentColorChangedBySystem;
_themeService.AccentColorChanged += AccentColorChanged; _themeService.AccentColorChanged += AccentColorChanged;
_themeService.ElementThemeChanged += ElementThemeChanged; _themeService.ElementThemeChanged += ElementThemeChanged;
_themeService.AccentColorChangedBySystem += AccentColorChangedBySystem;
}
private void AccentColorChangedBySystem(object sender, string newAccentColorHex)
{
var accentInList = Colors.FirstOrDefault(a => a.IsAccentColor);
if (accentInList != null)
{
accentInList.Hex = newAccentColorHex;
}
} }
private void AccentColorChanged(object sender, string e) private void AccentColorChanged(object sender, string e)
@@ -269,7 +257,6 @@ namespace Wino.Mail.ViewModels
_themeService.AccentColorChanged -= AccentColorChanged; _themeService.AccentColorChanged -= AccentColorChanged;
_themeService.ElementThemeChanged -= ElementThemeChanged; _themeService.ElementThemeChanged -= ElementThemeChanged;
_themeService.AccentColorChangedBySystem -= AccentColorChangedBySystem;
if (AppThemes != null) if (AppThemes != null)
{ {

View File

@@ -12,8 +12,8 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="5.0.4" /> <PackageReference Include="Microsoft.AppCenter.Crashes" Version="5.0.5" />
<PackageReference Include="System.Reactive" Version="6.0.0" /> <PackageReference Include="System.Reactive" Version="6.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -12,7 +12,6 @@ using Wino.Controls;
using Wino.Core.Domain; using Wino.Core.Domain;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Reader;
namespace Wino.Helpers namespace Wino.Helpers
{ {
@@ -284,109 +283,60 @@ namespace Wino.Helpers
#endregion #endregion
#region Toolbar Section Initialization
public static Visibility IsFormatSection(EditorToolbarSection section) => section?.SectionType == EditorToolbarSectionType.Format ? Visibility.Visible : Visibility.Collapsed;
public static Visibility IsInsertSection(EditorToolbarSection section) => section?.SectionType == EditorToolbarSectionType.Insert ? Visibility.Visible : Visibility.Collapsed;
public static Visibility IsDrawSection(EditorToolbarSection section) => section?.SectionType == EditorToolbarSectionType.Draw ? Visibility.Visible : Visibility.Collapsed;
public static Visibility IsOptionsSection(EditorToolbarSection section) => section?.SectionType == EditorToolbarSectionType.Options ? Visibility.Visible : Visibility.Collapsed;
#endregion
#region Internationalization #region Internationalization
public static string GetOperationString(MailOperation operation) public static string GetOperationString(MailOperation operation)
{ {
switch (operation) return operation switch
{ {
case MailOperation.None: MailOperation.None => "unknown",
return "unknown"; MailOperation.Archive => Translator.MailOperation_Archive,
case MailOperation.Archive: MailOperation.UnArchive => Translator.MailOperation_Unarchive,
return Translator.MailOperation_Archive; MailOperation.SoftDelete => Translator.MailOperation_Delete,
case MailOperation.UnArchive: MailOperation.HardDelete => Translator.MailOperation_Delete,
return Translator.MailOperation_Unarchive; MailOperation.Move => Translator.MailOperation_Move,
case MailOperation.SoftDelete: MailOperation.MoveToJunk => Translator.MailOperation_MoveJunk,
return Translator.MailOperation_Delete; MailOperation.MoveToFocused => Translator.MailOperation_MoveFocused,
case MailOperation.HardDelete: MailOperation.MoveToOther => Translator.MailOperation_MoveOther,
return Translator.MailOperation_Delete; MailOperation.AlwaysMoveToOther => Translator.MailOperation_AlwaysMoveOther,
case MailOperation.Move: MailOperation.AlwaysMoveToFocused => Translator.MailOperation_AlwaysMoveFocused,
return Translator.MailOperation_Move; MailOperation.SetFlag => Translator.MailOperation_SetFlag,
case MailOperation.MoveToJunk: MailOperation.ClearFlag => Translator.MailOperation_ClearFlag,
return Translator.MailOperation_MoveJunk; MailOperation.MarkAsRead => Translator.MailOperation_MarkAsRead,
case MailOperation.MoveToFocused: MailOperation.MarkAsUnread => Translator.MailOperation_MarkAsUnread,
return Translator.MailOperation_MoveFocused; MailOperation.MarkAsNotJunk => Translator.MailOperation_MarkNotJunk,
case MailOperation.MoveToOther: MailOperation.Seperator => string.Empty,
return Translator.MailOperation_MoveOther; MailOperation.Ignore => Translator.MailOperation_Ignore,
case MailOperation.AlwaysMoveToOther: MailOperation.Reply => Translator.MailOperation_Reply,
return Translator.MailOperation_AlwaysMoveOther; MailOperation.ReplyAll => Translator.MailOperation_ReplyAll,
case MailOperation.AlwaysMoveToFocused: MailOperation.Zoom => Translator.MailOperation_Zoom,
return Translator.MailOperation_AlwaysMoveFocused; MailOperation.SaveAs => Translator.MailOperation_SaveAs,
case MailOperation.SetFlag: MailOperation.Find => Translator.MailOperation_Find,
return Translator.MailOperation_SetFlag; MailOperation.Forward => Translator.MailOperation_Forward,
case MailOperation.ClearFlag: MailOperation.DarkEditor => string.Empty,
return Translator.MailOperation_ClearFlag; MailOperation.LightEditor => string.Empty,
case MailOperation.MarkAsRead: MailOperation.Print => Translator.MailOperation_Print,
return Translator.MailOperation_MarkAsRead; MailOperation.Navigate => Translator.MailOperation_Navigate,
case MailOperation.MarkAsUnread: _ => "unknown",
return Translator.MailOperation_MarkAsUnread; };
case MailOperation.MarkAsNotJunk:
return Translator.MailOperation_MarkNotJunk;
case MailOperation.Seperator:
return string.Empty;
case MailOperation.Ignore:
return Translator.MailOperation_Ignore;
case MailOperation.Reply:
return Translator.MailOperation_Reply;
case MailOperation.ReplyAll:
return Translator.MailOperation_ReplyAll;
case MailOperation.Zoom:
return Translator.MailOperation_Zoom;
case MailOperation.SaveAs:
return Translator.MailOperation_SaveAs;
case MailOperation.Find:
return Translator.MailOperation_Find;
case MailOperation.Forward:
return Translator.MailOperation_Forward;
case MailOperation.DarkEditor:
return string.Empty;
case MailOperation.LightEditor:
return string.Empty;
case MailOperation.Print:
return Translator.MailOperation_Print;
case MailOperation.Navigate:
return Translator.MailOperation_Navigate;
default:
return "unknown";
}
} }
public static string GetOperationString(FolderOperation operation) public static string GetOperationString(FolderOperation operation)
{ {
switch (operation) return operation switch
{ {
case FolderOperation.None: FolderOperation.None => string.Empty,
break; FolderOperation.Pin => Translator.FolderOperation_Pin,
case FolderOperation.Pin: FolderOperation.Unpin => Translator.FolderOperation_Unpin,
return Translator.FolderOperation_Pin; FolderOperation.MarkAllAsRead => Translator.FolderOperation_MarkAllAsRead,
case FolderOperation.Unpin: FolderOperation.DontSync => Translator.FolderOperation_DontSync,
return Translator.FolderOperation_Unpin; FolderOperation.Empty => Translator.FolderOperation_Empty,
case FolderOperation.MarkAllAsRead: FolderOperation.Rename => Translator.FolderOperation_Rename,
return Translator.FolderOperation_MarkAllAsRead; FolderOperation.Delete => Translator.FolderOperation_Delete,
case FolderOperation.DontSync: FolderOperation.Move => Translator.FolderOperation_Move,
return Translator.FolderOperation_DontSync; FolderOperation.CreateSubFolder => Translator.FolderOperation_CreateSubFolder,
case FolderOperation.Empty: _ => string.Empty,
return Translator.FolderOperation_Empty; };
case FolderOperation.Rename:
return Translator.FolderOperation_Rename;
case FolderOperation.Delete:
return Translator.FolderOperation_Delete;
case FolderOperation.Move:
return Translator.FolderOperation_Move;
case FolderOperation.CreateSubFolder:
return Translator.FolderOperation_CreateSubFolder;
}
return string.Empty;
} }
#endregion #endregion

View File

@@ -4,7 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:abstract="using:Wino.Views.Abstract" xmlns:abstract="using:Wino.Views.Abstract"
xmlns:controls="using:Wino.Controls" xmlns:controls="using:Wino.Controls"
xmlns:controls1="using:CommunityToolkit.WinUI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:data="using:Wino.Mail.ViewModels.Data" xmlns:data="using:Wino.Mail.ViewModels.Data"
xmlns:domain="using:Wino.Core.Domain" xmlns:domain="using:Wino.Core.Domain"
@@ -14,6 +13,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls" xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:reader="using:Wino.Core.Domain.Models.Reader" xmlns:reader="using:Wino.Core.Domain.Models.Reader"
xmlns:toolkit="using:CommunityToolkit.WinUI.Controls"
x:Name="root" x:Name="root"
d:Background="White" d:Background="White"
Loaded="ComposerLoaded" Loaded="ComposerLoaded"
@@ -144,26 +144,22 @@
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="56" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid <!-- Format -->
x:Name="TopPanelGrid" <toolkit:TabbedCommandBar>
Padding="16,6,6,6" <toolkit:TabbedCommandBar.Resources>
RowSpacing="6"> <SolidColorBrush x:Key="TabContentContentBorderBackground" Color="Transparent" />
<Grid.RowDefinitions> <SolidColorBrush x:Key="TabContentContentBorderBorderBrush" Color="Transparent" />
<RowDefinition Height="Auto" /> <Thickness x:Key="TabContentBorderBorderThickness">0</Thickness>
<RowDefinition Height="*" /> </toolkit:TabbedCommandBar.Resources>
</Grid.RowDefinitions> <toolkit:TabbedCommandBar.PaneCustomContent>
<CommandBar <toolkit:TabbedCommandBarItem
Grid.Row="1" CommandAlignment="Right"
DefaultLabelPosition="Right" IsDynamicOverflowEnabled="True"
DynamicOverflowItemsChanging="BarDynamicOverflowChanging" OverflowButtonAlignment="Left">
IsDynamicOverflowEnabled="True"
OverflowButtonVisibility="Collapsed">
<CommandBar.PrimaryCommands>
<AppBarButton <AppBarButton
Click="InvertComposerThemeClicked" Click="InvertComposerThemeClicked"
LabelPosition="Collapsed" LabelPosition="Collapsed"
@@ -184,252 +180,229 @@
</AppBarButton.Icon> </AppBarButton.Icon>
</AppBarButton> </AppBarButton>
<AppBarButton Command="{x:Bind ViewModel.DiscardCommand}" Label="Discard"> <AppBarButton Command="{x:Bind ViewModel.DiscardCommand}" Label="{x:Bind domain:Translator.Buttons_Discard}">
<AppBarButton.Icon> <AppBarButton.Icon>
<controls:WinoFontIcon Icon="Delete" /> <controls:WinoFontIcon Icon="Delete" />
</AppBarButton.Icon> </AppBarButton.Icon>
</AppBarButton> </AppBarButton>
<AppBarButton Command="{x:Bind ViewModel.SendCommand}" Label="Send"> <AppBarButton Command="{x:Bind ViewModel.SendCommand}" Label="{x:Bind domain:Translator.Buttons_Send}">
<AppBarButton.Icon> <AppBarButton.Icon>
<controls:WinoFontIcon Icon="Send" /> <controls:WinoFontIcon Icon="Send" />
</AppBarButton.Icon> </AppBarButton.Icon>
</AppBarButton> </AppBarButton>
</CommandBar.PrimaryCommands> </toolkit:TabbedCommandBarItem>
<CommandBar.Content> </toolkit:TabbedCommandBar.PaneCustomContent>
<!-- Wino Pivot --> <toolkit:TabbedCommandBar.MenuItems>
<controls:WinoPivotControl <toolkit:TabbedCommandBarItem DefaultLabelPosition="Collapsed" Header="{x:Bind domain:Translator.EditorToolbarOption_Format}">
ItemsSource="{x:Bind ViewModel.ToolbarSections}" <AppBarToggleButton
SelectedItem="{x:Bind ViewModel.SelectedToolbarSection, Mode=TwoWay}" x:Name="BoldButton"
SelectorPipeColor="{ThemeResource NavigationViewSelectionIndicatorForeground}"> Click="BoldButtonClicked"
<controls:WinoPivotControl.DataTemplate> Label="Bold">
<DataTemplate x:DataType="reader:EditorToolbarSection"> <AppBarToggleButton.Icon>
<TextBlock Text="{x:Bind Title}" /> <PathIcon Data="{StaticResource BoldPathIcon}" />
</DataTemplate> </AppBarToggleButton.Icon>
</controls:WinoPivotControl.DataTemplate> </AppBarToggleButton>
</controls:WinoPivotControl> <AppBarToggleButton
</CommandBar.Content> x:Name="ItalicButton"
</CommandBar> Click="ItalicButtonClicked"
</Grid> Label="Italic">
<AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource ItalicPathIcon}" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
<AppBarToggleButton
x:Name="UnderlineButton"
Click="UnderlineButtonClicked"
Label="Underline">
<AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource UnderlinePathIcon}" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
<AppBarToggleButton
x:Name="StrokeButton"
Click="StrokeButtonClicked"
Label="Stroke">
<AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource StrikePathIcon}" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
<!-- Editor Options --> <AppBarSeparator />
<Grid Grid.Row="1" Padding="26,0,6,6">
<CommandBar
HorizontalAlignment="Left"
DefaultLabelPosition="Collapsed"
IsDynamicOverflowEnabled="True"
Visibility="{x:Bind helpers:XamlHelpers.IsFormatSection(ViewModel.SelectedToolbarSection), Mode=OneWay}">
<AppBarToggleButton
x:Name="BoldButton"
Click="BoldButtonClicked"
Label="Bold">
<AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource BoldPathIcon}" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
<AppBarToggleButton
x:Name="ItalicButton"
Click="ItalicButtonClicked"
Label="Italic">
<AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource ItalicPathIcon}" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
<AppBarToggleButton
x:Name="UnderlineButton"
Click="UnderlineButtonClicked"
Label="Underline">
<AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource UnderlinePathIcon}" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
<AppBarToggleButton
x:Name="StrokeButton"
Click="StrokeButtonClicked"
Label="Stroke">
<AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource StrikePathIcon}" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
<AppBarSeparator /> <AppBarToggleButton
x:Name="BulletListButton"
Click="BulletListButtonClicked"
Label="Bullet List">
<AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource BulletedListPathIcon}" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
<AppBarToggleButton <AppBarToggleButton
x:Name="BulletListButton" x:Name="OrderedListButton"
Click="BulletListButtonClicked" Click="OrderedListButtonClicked"
Label="Bullet List"> Label="Ordered List">
<AppBarToggleButton.Icon> <AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource BulletedListPathIcon}" /> <PathIcon Data="{StaticResource OrderedListPathIcon}" />
</AppBarToggleButton.Icon> </AppBarToggleButton.Icon>
</AppBarToggleButton> </AppBarToggleButton>
<AppBarToggleButton <AppBarSeparator />
x:Name="OrderedListButton"
Click="OrderedListButtonClicked"
Label="Ordered List">
<AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource OrderedListPathIcon}" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
<AppBarSeparator /> <AppBarButton
x:Name="DecreaseIndentButton"
Click="DecreaseIndentClicked"
Label="Outdent">
<AppBarButton.Content>
<Viewbox Width="16">
<PathIcon Data="{StaticResource DecreaseIndentPathIcon}" />
</Viewbox>
</AppBarButton.Content>
</AppBarButton>
<AppBarButton <AppBarButton
x:Name="DecreaseIndentButton" x:Name="IncreaseIndentButton"
Click="DecreaseIndentClicked" Click="IncreaseIndentClicked"
Label="Outdent"> Label="Indent">
<AppBarButton.Content> <AppBarButton.Content>
<Viewbox Width="16"> <Viewbox Width="16">
<PathIcon Data="{StaticResource DecreaseIndentPathIcon}" /> <PathIcon Data="{StaticResource IncreaseIndentPathIcon}" />
</Viewbox> </Viewbox>
</AppBarButton.Content> </AppBarButton.Content>
</AppBarButton> </AppBarButton>
<AppBarButton <AppBarElementContainer HorizontalAlignment="Center" VerticalAlignment="Center">
x:Name="IncreaseIndentButton" <ComboBox
Click="IncreaseIndentClicked" x:Name="AlignmentListView"
Label="Indent"> VerticalAlignment="Center"
<AppBarButton.Content> Background="Transparent"
<Viewbox Width="16"> BorderBrush="Transparent"
<PathIcon Data="{StaticResource IncreaseIndentPathIcon}" /> SelectionChanged="AlignmentChanged">
</Viewbox> <ComboBoxItem IsSelected="True" Tag="left">
</AppBarButton.Content> <StackPanel Orientation="Horizontal" Spacing="8">
</AppBarButton> <Viewbox Width="16">
<PathIcon Data="{StaticResource AlignLeftPathIcon}" />
</Viewbox>
<TextBlock VerticalAlignment="Center" Text="{x:Bind domain:Translator.Left}" />
</StackPanel>
</ComboBoxItem>
<AppBarElementContainer HorizontalAlignment="Center" VerticalAlignment="Center"> <ComboBoxItem Tag="center">
<ComboBox <StackPanel Orientation="Horizontal" Spacing="8">
x:Name="AlignmentListView" <Viewbox Width="16">
VerticalAlignment="Center" <PathIcon Data="{StaticResource AlignCenterPathIcon}" />
Background="Transparent" </Viewbox>
BorderBrush="Transparent" <TextBlock VerticalAlignment="Center" Text="{x:Bind domain:Translator.Center}" />
SelectionChanged="AlignmentChanged"> </StackPanel>
<ComboBoxItem IsSelected="True" Tag="left"> </ComboBoxItem>
<StackPanel Orientation="Horizontal" Spacing="8">
<Viewbox Width="16">
<PathIcon Data="{StaticResource AlignLeftPathIcon}" />
</Viewbox>
<TextBlock VerticalAlignment="Center" Text="{x:Bind domain:Translator.Left}" />
</StackPanel>
</ComboBoxItem>
<ComboBoxItem Tag="center"> <ComboBoxItem Tag="right">
<StackPanel Orientation="Horizontal" Spacing="8"> <StackPanel Orientation="Horizontal" Spacing="8">
<Viewbox Width="16"> <Viewbox Width="16">
<PathIcon Data="{StaticResource AlignCenterPathIcon}" /> <PathIcon Data="{StaticResource AlignRightPathIcon}" />
</Viewbox> </Viewbox>
<TextBlock VerticalAlignment="Center" Text="{x:Bind domain:Translator.Center}" /> <TextBlock VerticalAlignment="Center" Text="{x:Bind domain:Translator.Right}" />
</StackPanel> </StackPanel>
</ComboBoxItem> </ComboBoxItem>
<ComboBoxItem Tag="right"> <ComboBoxItem Tag="justify">
<StackPanel Orientation="Horizontal" Spacing="8"> <StackPanel Orientation="Horizontal" Spacing="8">
<Viewbox Width="16"> <Viewbox Width="16">
<PathIcon Data="{StaticResource AlignRightPathIcon}" /> <PathIcon Data="{StaticResource AlignJustifyPathIcon}" />
</Viewbox> </Viewbox>
<TextBlock VerticalAlignment="Center" Text="{x:Bind domain:Translator.Right}" /> <TextBlock VerticalAlignment="Center" Text="{x:Bind domain:Translator.Justify}" />
</StackPanel> </StackPanel>
</ComboBoxItem> </ComboBoxItem>
</ComboBox>
</AppBarElementContainer>
<ComboBoxItem Tag="justify"> <AppBarSeparator />
<StackPanel Orientation="Horizontal" Spacing="8">
<Viewbox Width="16">
<PathIcon Data="{StaticResource AlignJustifyPathIcon}" />
</Viewbox>
<TextBlock VerticalAlignment="Center" Text="{x:Bind domain:Translator.Justify}" />
</StackPanel>
</ComboBoxItem>
</ComboBox>
</AppBarElementContainer>
<AppBarSeparator /> <AppBarToggleButton
x:Name="WebviewToolBarButton"
Click="WebViewToggleButtonClicked"
Label="{x:Bind domain:Translator.EditorTooltip_WebViewEditor}"
ToolTipService.ToolTip="{x:Bind domain:Translator.EditorTooltip_WebViewEditor}">
<AppBarToggleButton.Icon>
<PathIcon Data="{StaticResource WebviewToolBarPathIcon}" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
</toolkit:TabbedCommandBarItem>
<AppBarToggleButton <!-- Insert -->
x:Name="WebviewToolBarButton" <toolkit:TabbedCommandBarItem Header="{x:Bind domain:Translator.EditorToolbarOption_Insert}">
Click="WebViewToggleButtonClicked" <AppBarButton
Label="{x:Bind domain:Translator.EditorTooltip_WebViewEditor}" x:Name="FilesButton"
ToolTipService.ToolTip="{x:Bind domain:Translator.EditorTooltip_WebViewEditor}"> Click="AddFilesClicked"
<AppBarToggleButton.Icon> Label="{x:Bind domain:Translator.Files}">
<PathIcon Data="{StaticResource WebviewToolBarPathIcon}" /> <AppBarButton.Icon>
</AppBarToggleButton.Icon> <PathIcon Data="{StaticResource AttachPathIcon}" />
</AppBarToggleButton> </AppBarButton.Icon>
</CommandBar> </AppBarButton>
<!-- Insert Panel --> <AppBarButton
<CommandBar x:Name="AddImageButton"
HorizontalAlignment="Left" Click="AddImageClicked"
DefaultLabelPosition="Right" Label="{x:Bind domain:Translator.Photos}">
IsDynamicOverflowEnabled="True" <AppBarButton.Icon>
Visibility="{x:Bind helpers:XamlHelpers.IsInsertSection(ViewModel.SelectedToolbarSection), Mode=OneWay}"> <PathIcon Data="{StaticResource AddPhotoPathIcon}" />
<AppBarButton </AppBarButton.Icon>
x:Name="FilesButton" </AppBarButton>
Click="AddFilesClicked"
Label="{x:Bind domain:Translator.Files}">
<AppBarButton.Icon>
<PathIcon Data="{StaticResource AttachPathIcon}" />
</AppBarButton.Icon>
</AppBarButton>
<AppBarButton <AppBarButton
x:Name="AddImageButton" x:Name="EmojiButton"
Click="AddImageClicked" Click="EmojiButtonClicked"
Label="{x:Bind domain:Translator.Photos}"> Label="{x:Bind domain:Translator.Emoji}">
<AppBarButton.Icon> <AppBarButton.Icon>
<PathIcon Data="{StaticResource AddPhotoPathIcon}" /> <PathIcon Data="{StaticResource EmojiPathIcon}" />
</AppBarButton.Icon> </AppBarButton.Icon>
</AppBarButton> </AppBarButton>
</toolkit:TabbedCommandBarItem>
<AppBarButton <!-- Options -->
x:Name="EmojiButton" <toolkit:TabbedCommandBarItem Header="{x:Bind domain:Translator.EditorToolbarOption_Options}">
Click="EmojiButtonClicked" <AppBarElementContainer>
Label="{x:Bind domain:Translator.Emoji}"> <muxc:ToggleSplitButton x:Name="ImportanceSplitButton" IsChecked="{x:Bind ViewModel.IsImportanceSelected, Mode=TwoWay}">
<AppBarButton.Icon> <FontIcon
<PathIcon Data="{StaticResource EmojiPathIcon}" /> FontFamily="Segoe Fluent Icons"
</AppBarButton.Icon> FontSize="16"
</AppBarButton> Glyph="&#xE8C9;" />
</CommandBar> <muxc:ToggleSplitButton.Flyout>
<Flyout x:Name="ImportanceFlyout" Placement="Bottom">
<!-- Draw Panel --> <StackPanel Orientation="Horizontal">
<Grid x:Name="DrawPanel" Visibility="{x:Bind helpers:XamlHelpers.IsDrawSection(ViewModel.SelectedToolbarSection), Mode=OneWay}"> <StackPanel.Resources>
<TextBlock Text="{x:Bind domain:Translator.ComingSoon}" /> <Style TargetType="Button">
</Grid> <Setter Property="Padding" Value="4" />
<Setter Property="MinWidth" Value="0" />
<!-- Options Panel --> <Setter Property="MinHeight" Value="0" />
<Grid x:Name="OptionsPanel" Visibility="{x:Bind helpers:XamlHelpers.IsOptionsSection(ViewModel.SelectedToolbarSection), Mode=OneWay}"> <Setter Property="Margin" Value="6" />
<muxc:ToggleSplitButton x:Name="ImportanceSplitButton" IsChecked="{x:Bind ViewModel.IsImportanceSelected, Mode=TwoWay}"> <Setter Property="CornerRadius" Value="{StaticResource ControlCornerRadius}" />
<SymbolIcon x:Name="ImportanceSplitButtonContent" Symbol="Important" /> </Style>
<muxc:ToggleSplitButton.Flyout> </StackPanel.Resources>
<Flyout x:Name="ImportanceFlyout" Placement="Bottom"> <Button Click="ImportanceClicked">
<StackPanel Orientation="Horizontal"> <Button.Tag>
<StackPanel.Resources> <mailkit:MessageImportance>High</mailkit:MessageImportance>
<Style TargetType="Button"> </Button.Tag>
<Setter Property="Padding" Value="4" /> <FontIcon FontFamily="Segoe Fluent Icons" Glyph="&#xE8C9;" />
<Setter Property="MinWidth" Value="0" /> </Button>
<Setter Property="MinHeight" Value="0" /> <Button Click="ImportanceClicked">
<Setter Property="Margin" Value="6" /> <Button.Tag>
<Setter Property="CornerRadius" Value="{StaticResource ControlCornerRadius}" /> <mailkit:MessageImportance>Low</mailkit:MessageImportance>
</Style> </Button.Tag>
</StackPanel.Resources> <FontIcon FontFamily="Segoe Fluent Icons" Glyph="&#xE8D0;" />
<Button Click="ImportanceClicked"> </Button>
<Button.Tag> </StackPanel>
<mailkit:MessageImportance>High</mailkit:MessageImportance> </Flyout>
</Button.Tag> </muxc:ToggleSplitButton.Flyout>
<SymbolIcon Symbol="Important" /> </muxc:ToggleSplitButton>
</Button> </AppBarElementContainer>
<Button Click="ImportanceClicked"> </toolkit:TabbedCommandBarItem>
<Button.Tag> </toolkit:TabbedCommandBar.MenuItems>
<mailkit:MessageImportance>Low</mailkit:MessageImportance> </toolkit:TabbedCommandBar>
</Button.Tag>
<SymbolIcon Symbol="Download" />
</Button>
</StackPanel>
</Flyout>
</muxc:ToggleSplitButton.Flyout>
</muxc:ToggleSplitButton>
</Grid>
</Grid>
<!-- Mime Info --> <!-- Mime Info -->
<Grid <Grid
Grid.Row="2" Grid.Row="1"
Padding="16,0,16,10" Padding="16,0,16,10"
ColumnSpacing="12" ColumnSpacing="12"
RowSpacing="3"> RowSpacing="3">
@@ -478,7 +451,7 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<controls1:TokenizingTextBox <toolkit:TokenizingTextBox
x:Name="ToBox" x:Name="ToBox"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
@@ -520,7 +493,7 @@
Text="Cc: " Text="Cc: "
Visibility="{x:Bind ViewModel.IsCCBCCVisible, Mode=OneWay}" /> Visibility="{x:Bind ViewModel.IsCCBCCVisible, Mode=OneWay}" />
<controls1:TokenizingTextBox <toolkit:TokenizingTextBox
x:Name="CCBox" x:Name="CCBox"
Grid.Row="2" Grid.Row="2"
Grid.Column="1" Grid.Column="1"
@@ -543,7 +516,7 @@
Text="Bcc: " Text="Bcc: "
Visibility="{x:Bind ViewModel.IsCCBCCVisible, Mode=OneWay}" /> Visibility="{x:Bind ViewModel.IsCCBCCVisible, Mode=OneWay}" />
<controls1:TokenizingTextBox <toolkit:TokenizingTextBox
x:Name="BccBox" x:Name="BccBox"
Grid.Row="3" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
@@ -586,7 +559,7 @@
SelectionMode="None"> SelectionMode="None">
<ListView.ItemsPanel> <ListView.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<controls1:WrapPanel Orientation="Horizontal" /> <toolkit:WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate> </ItemsPanelTemplate>
</ListView.ItemsPanel> </ListView.ItemsPanel>
</ListView> </ListView>
@@ -595,7 +568,7 @@
<!-- Dropzone --> <!-- Dropzone -->
<Grid <Grid
Grid.Row="0" Grid.Row="0"
Grid.RowSpan="3" Grid.RowSpan="2"
AllowDrop="True" AllowDrop="True"
DragLeave="OnFileDropGridDragLeave" DragLeave="OnFileDropGridDragLeave"
DragOver="OnFileDropGridDragOver" DragOver="OnFileDropGridDragOver"

View File

@@ -26,7 +26,6 @@ using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation; using Windows.UI.Xaml.Navigation;
using Wino.Core.Domain; using Wino.Core.Domain;
using Wino.Core.Domain.Entities; using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Reader; using Wino.Core.Domain.Models.Reader;
using Wino.Extensions; using Wino.Extensions;
@@ -38,7 +37,6 @@ using Wino.Views.Abstract;
namespace Wino.Views namespace Wino.Views
{ {
public sealed partial class ComposePage : ComposePageAbstract, public sealed partial class ComposePage : ComposePageAbstract,
IRecipient<NavigationPaneModeChanged>,
IRecipient<CreateNewComposeMailRequested>, IRecipient<CreateNewComposeMailRequested>,
IRecipient<ApplicationThemeChanged> IRecipient<ApplicationThemeChanged>
{ {
@@ -170,6 +168,7 @@ namespace Wino.Views
ViewModel.IsDraggingOverFilesDropZone = false; ViewModel.IsDraggingOverFilesDropZone = false;
} }
} }
private void OnImageDropGridDragEnter(object sender, DragEventArgs e) private void OnImageDropGridDragEnter(object sender, DragEventArgs e)
{ {
bool isValid = false; bool isValid = false;
@@ -557,27 +556,11 @@ namespace Wino.Views
private void DOMLoaded(CoreWebView2 sender, CoreWebView2DOMContentLoadedEventArgs args) => DOMLoadedTask.TrySetResult(true); private void DOMLoaded(CoreWebView2 sender, CoreWebView2DOMContentLoadedEventArgs args) => DOMLoadedTask.TrySetResult(true);
void IRecipient<NavigationPaneModeChanged>.Receive(NavigationPaneModeChanged message)
{
if (message.NewMode == MenuPaneMode.Hidden)
TopPanelGrid.Padding = new Thickness(48, 6, 6, 6);
else
TopPanelGrid.Padding = new Thickness(16, 6, 6, 6);
}
async void IRecipient<CreateNewComposeMailRequested>.Receive(CreateNewComposeMailRequested message) async void IRecipient<CreateNewComposeMailRequested>.Receive(CreateNewComposeMailRequested message)
{ {
await RenderInternalAsync(message.RenderModel.RenderHtml); await RenderInternalAsync(message.RenderModel.RenderHtml);
} }
private void BarDynamicOverflowChanging(CommandBar sender, DynamicOverflowItemsChangingEventArgs args)
{
if (args.Action == CommandBarDynamicOverflowAction.AddingToOverflow)
sender.OverflowButtonVisibility = CommandBarOverflowButtonVisibility.Visible;
else
sender.OverflowButtonVisibility = CommandBarOverflowButtonVisibility.Collapsed;
}
private void ShowCCBCCClicked(object sender, RoutedEventArgs e) private void ShowCCBCCClicked(object sender, RoutedEventArgs e)
{ {
ViewModel.IsCCBCCVisible = true; ViewModel.IsCCBCCVisible = true;
@@ -641,7 +624,7 @@ namespace Wino.Views
var selectedImportance = (MessageImportance)senderButton.Tag; var selectedImportance = (MessageImportance)senderButton.Tag;
ViewModel.SelectedMessageImportance = selectedImportance; ViewModel.SelectedMessageImportance = selectedImportance;
(ImportanceSplitButton.Content as SymbolIcon).Symbol = (senderButton.Content as SymbolIcon).Symbol; (ImportanceSplitButton.Content as FontIcon).Glyph = (senderButton.Content as FontIcon).Glyph;
} }
} }

View File

@@ -39,7 +39,7 @@ namespace Wino.Views
IRecipient<ShellStateUpdated>, IRecipient<ShellStateUpdated>,
IRecipient<DisposeRenderingFrameRequested> IRecipient<DisposeRenderingFrameRequested>
{ {
private const double RENDERING_COLUMN_MIN_WIDTH = 300; private const double RENDERING_COLUMN_MIN_WIDTH = 375;
private IStatePersistanceService StatePersistenceService { get; } = App.Current.Services.GetService<IStatePersistanceService>(); private IStatePersistanceService StatePersistenceService { get; } = App.Current.Services.GetService<IStatePersistanceService>();
private IKeyPressService KeyPressService { get; } = App.Current.Services.GetService<IKeyPressService>(); private IKeyPressService KeyPressService { get; } = App.Current.Services.GetService<IKeyPressService>();

View File

@@ -25,7 +25,6 @@ namespace Wino.Views
public sealed partial class MailRenderingPage : MailRenderingPageAbstract, public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
IRecipient<HtmlRenderingRequested>, IRecipient<HtmlRenderingRequested>,
IRecipient<CancelRenderingContentRequested>, IRecipient<CancelRenderingContentRequested>,
IRecipient<NavigationPaneModeChanged>,
IRecipient<ApplicationThemeChanged>, IRecipient<ApplicationThemeChanged>,
IRecipient<SaveAsPDFRequested> IRecipient<SaveAsPDFRequested>
{ {
@@ -208,14 +207,6 @@ namespace Wino.Views
} }
} }
void IRecipient<NavigationPaneModeChanged>.Receive(NavigationPaneModeChanged message)
{
if (message.NewMode == MenuPaneMode.Hidden)
RendererBar.Margin = new Thickness(48, 6, 6, 6);
else
RendererBar.Margin = new Thickness(16, 6, 6, 6);
}
private async void WebViewNavigationStarting(WebView2 sender, CoreWebView2NavigationStartingEventArgs args) private async void WebViewNavigationStarting(WebView2 sender, CoreWebView2NavigationStartingEventArgs args)
{ {
// This is our reader. // This is our reader.

View File

@@ -136,28 +136,31 @@
<Version>8.2.2</Version> <Version>8.2.2</Version>
</PackageReference> </PackageReference>
<PackageReference Include="CommunityToolkit.Uwp.Animations"> <PackageReference Include="CommunityToolkit.Uwp.Animations">
<Version>8.0.240109</Version> <Version>8.1.240821</Version>
</PackageReference> </PackageReference>
<PackageReference Include="CommunityToolkit.Uwp.Behaviors"> <PackageReference Include="CommunityToolkit.Uwp.Behaviors">
<Version>8.0.240109</Version> <Version>8.1.240821</Version>
</PackageReference> </PackageReference>
<PackageReference Include="CommunityToolkit.Uwp.Controls.SettingsControls"> <PackageReference Include="CommunityToolkit.Uwp.Controls.SettingsControls">
<Version>8.0.240109</Version> <Version>8.1.240821</Version>
</PackageReference> </PackageReference>
<PackageReference Include="CommunityToolkit.Uwp.Controls.Sizers"> <PackageReference Include="CommunityToolkit.Uwp.Controls.Sizers">
<Version>8.0.240109</Version> <Version>8.1.240821</Version>
</PackageReference>
<PackageReference Include="CommunityToolkit.Uwp.Controls.TabbedCommandBar">
<Version>8.1.240821</Version>
</PackageReference> </PackageReference>
<PackageReference Include="CommunityToolkit.Uwp.Controls.TokenizingTextBox"> <PackageReference Include="CommunityToolkit.Uwp.Controls.TokenizingTextBox">
<Version>8.0.240109</Version> <Version>8.1.240821</Version>
</PackageReference> </PackageReference>
<PackageReference Include="EmailValidation"> <PackageReference Include="EmailValidation">
<Version>1.2.0</Version> <Version>1.2.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.AppCenter.Analytics"> <PackageReference Include="Microsoft.AppCenter.Analytics">
<Version>5.0.4</Version> <Version>5.0.5</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.AppCenter.Crashes"> <PackageReference Include="Microsoft.AppCenter.Crashes">
<Version>5.0.4</Version> <Version>5.0.5</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection"> <PackageReference Include="Microsoft.Extensions.DependencyInjection">
<Version>8.0.0</Version> <Version>8.0.0</Version>
@@ -183,16 +186,16 @@
<Version>5.1.2</Version> <Version>5.1.2</Version>
</PackageReference> </PackageReference>
<PackageReference Include="ReactiveUI"> <PackageReference Include="ReactiveUI">
<Version>19.6.1</Version> <Version>20.1.1</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Serilog"> <PackageReference Include="Serilog">
<Version>3.1.1</Version> <Version>4.0.1</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Serilog.Exceptions"> <PackageReference Include="Serilog.Exceptions">
<Version>8.4.0</Version> <Version>8.4.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="sqlite-net-pcl"> <PackageReference Include="sqlite-net-pcl">
<Version>1.8.116</Version> <Version>1.9.172</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Win2D.uwp"> <PackageReference Include="Win2D.uwp">
<Version>1.27.1</Version> <Version>1.27.1</Version>

View File

@@ -1,10 +0,0 @@
using Wino.Core.Domain.Enums;
namespace Wino.Messaging.Client.Shell
{
/// <summary>
/// When navigation pane mode is changed.
/// </summary>
/// <param name="NewMode">New navigation mode.</param>
public record NavigationPaneModeChanged(MenuPaneMode NewMode);
}

View File

@@ -11,7 +11,7 @@
<Identity <Identity
Name="58272BurakKSE.WinoMailPreview" Name="58272BurakKSE.WinoMailPreview"
Publisher="CN=51FBDAF3-E212-4149-89A2-A2636B3BC911" Publisher="CN=51FBDAF3-E212-4149-89A2-A2636B3BC911"
Version="1.8.3.0" /> Version="1.8.5.0" />
<Extensions> <Extensions>
<!-- Publisher Cache Folders --> <!-- Publisher Cache Folders -->

View File

@@ -129,7 +129,7 @@
</ItemGroup> </ItemGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" /> <Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.3233" PrivateAssets="all" /> <PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1" PrivateAssets="all" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Wino.Mail\Wino.Mail.csproj" /> <ProjectReference Include="..\Wino.Mail\Wino.Mail.csproj" />

View File

@@ -31,7 +31,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="H.NotifyIcon.Wpf" Version="2.1.2" /> <PackageReference Include="H.NotifyIcon.Wpf" Version="2.1.3" />
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" /> <PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>