UIMessage communication. Single instancing for server and re-connection mechanism on suspension.
This commit is contained in:
@@ -1,13 +1,4 @@
|
|||||||
using System;
|
using Windows.ApplicationModel.Background;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Serilog;
|
|
||||||
using Windows.ApplicationModel.Background;
|
|
||||||
using Windows.Storage;
|
|
||||||
using Wino.Core;
|
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
using Wino.Core.Services;
|
|
||||||
using Wino.Core.UWP;
|
|
||||||
using Wino.Services;
|
|
||||||
|
|
||||||
namespace Wino.BackgroundTasks
|
namespace Wino.BackgroundTasks
|
||||||
{
|
{
|
||||||
@@ -17,32 +8,34 @@ namespace Wino.BackgroundTasks
|
|||||||
{
|
{
|
||||||
var def = taskInstance.GetDeferral();
|
var def = taskInstance.GetDeferral();
|
||||||
|
|
||||||
try
|
//try
|
||||||
{
|
//{
|
||||||
var services = new ServiceCollection();
|
// var services = new ServiceCollection();
|
||||||
|
|
||||||
services.RegisterCoreServices();
|
// services.RegisterCoreServices();
|
||||||
services.RegisterCoreUWPServices();
|
// services.RegisterCoreUWPServices();
|
||||||
|
|
||||||
var providere = services.BuildServiceProvider();
|
// var providere = services.BuildServiceProvider();
|
||||||
|
|
||||||
var backgroundTaskService = providere.GetService<IBackgroundSynchronizer>();
|
// var backgroundTaskService = providere.GetService<IBackgroundSynchronizer>();
|
||||||
var dbService = providere.GetService<IDatabaseService>();
|
// var dbService = providere.GetService<IDatabaseService>();
|
||||||
var logInitializer = providere.GetService<ILogInitializer>();
|
// var logInitializer = providere.GetService<ILogInitializer>();
|
||||||
|
|
||||||
logInitializer.SetupLogger(ApplicationData.Current.LocalFolder.Path);
|
// logInitializer.SetupLogger(ApplicationData.Current.LocalFolder.Path);
|
||||||
|
|
||||||
await dbService.InitializeAsync();
|
// await dbService.InitializeAsync();
|
||||||
await backgroundTaskService.RunBackgroundSynchronizationAsync(Core.Domain.Enums.BackgroundSynchronizationReason.SessionConnected);
|
// await backgroundTaskService.RunBackgroundSynchronizationAsync(Core.Domain.Enums.BackgroundSynchronizationReason.SessionConnected);
|
||||||
}
|
//}
|
||||||
catch (Exception ex)
|
//catch (Exception ex)
|
||||||
{
|
//{
|
||||||
Log.Error(ex, "Background synchronization failed from background task.");
|
// Log.Error(ex, "Background synchronization failed from background task.");
|
||||||
}
|
//}
|
||||||
finally
|
//finally
|
||||||
{
|
//{
|
||||||
def.Complete();
|
// def.Complete();
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
def.Complete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,6 @@
|
|||||||
/// They are sent either from processor or view models to signal some other
|
/// They are sent either from processor or view models to signal some other
|
||||||
/// parts of the application.
|
/// parts of the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
public interface IServerMessage;
|
public interface IServerMessage;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
using System.Threading.Tasks;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
|
|
||||||
namespace Wino.Core.Domain.Interfaces
|
namespace Wino.Core.Domain.Interfaces
|
||||||
{
|
{
|
||||||
public interface IWinoServerConnectionManager
|
public interface IWinoServerConnectionManager
|
||||||
{
|
{
|
||||||
WinoServerConnectionStatus Status { get; }
|
|
||||||
Task<bool> ConnectAsync();
|
Task<bool> ConnectAsync();
|
||||||
Task<bool> DisconnectAsync();
|
Task<bool> DisconnectAsync();
|
||||||
|
|
||||||
|
WinoServerConnectionStatus Status { get; }
|
||||||
|
event EventHandler<WinoServerConnectionStatus> StatusChanged;
|
||||||
|
void DisposeConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IWinoServerConnectionManager<TAppServiceConnection> : IWinoServerConnectionManager, IInitializeAsync
|
public interface IWinoServerConnectionManager<TAppServiceConnection> : IWinoServerConnectionManager, IInitializeAsync
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ namespace Wino.Core.UWP
|
|||||||
services.AddTransient<IFileService, FileService>();
|
services.AddTransient<IFileService, FileService>();
|
||||||
services.AddTransient<IStoreRatingService, StoreRatingService>();
|
services.AddTransient<IStoreRatingService, StoreRatingService>();
|
||||||
services.AddTransient<IKeyPressService, KeyPressService>();
|
services.AddTransient<IKeyPressService, KeyPressService>();
|
||||||
services.AddTransient<IBackgroundSynchronizer, BackgroundSynchronizer>();
|
|
||||||
services.AddTransient<INotificationBuilder, NotificationBuilder>();
|
services.AddTransient<INotificationBuilder, NotificationBuilder>();
|
||||||
services.AddTransient<IClipboardService, ClipboardService>();
|
services.AddTransient<IClipboardService, ClipboardService>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,144 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Serilog;
|
|
||||||
using Windows.Storage;
|
|
||||||
using Wino.Core;
|
|
||||||
using Wino.Core.Domain.Enums;
|
|
||||||
using Wino.Core.Domain.Exceptions;
|
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
using Wino.Core.Domain.Models.Synchronization;
|
|
||||||
using Wino.Core.Synchronizers;
|
|
||||||
|
|
||||||
namespace Wino.Services
|
|
||||||
{
|
|
||||||
public interface IBackgroundSynchronizer
|
|
||||||
{
|
|
||||||
Task RunBackgroundSynchronizationAsync(BackgroundSynchronizationReason reason);
|
|
||||||
void CreateLock();
|
|
||||||
void ReleaseLock();
|
|
||||||
bool IsBackgroundSynchronizationLocked();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Service responsible for handling background synchronization on timer and session connected events.
|
|
||||||
/// </summary>
|
|
||||||
public class BackgroundSynchronizer : IBackgroundSynchronizer
|
|
||||||
{
|
|
||||||
private const string BackgroundSynchronizationLock = nameof(BackgroundSynchronizationLock);
|
|
||||||
|
|
||||||
private readonly IAccountService _accountService;
|
|
||||||
private readonly IFolderService _folderService;
|
|
||||||
private readonly IWinoSynchronizerFactory _winoSynchronizerFactory;
|
|
||||||
|
|
||||||
public BackgroundSynchronizer(IAccountService accountService,
|
|
||||||
IFolderService folderService,
|
|
||||||
IWinoSynchronizerFactory winoSynchronizerFactory)
|
|
||||||
{
|
|
||||||
_accountService = accountService;
|
|
||||||
_folderService = folderService;
|
|
||||||
_winoSynchronizerFactory = winoSynchronizerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CreateLock() => ApplicationData.Current.LocalSettings.Values[BackgroundSynchronizationLock] = true;
|
|
||||||
public void ReleaseLock() => ApplicationData.Current.LocalSettings.Values[BackgroundSynchronizationLock] = false;
|
|
||||||
|
|
||||||
public bool IsBackgroundSynchronizationLocked()
|
|
||||||
=> ApplicationData.Current.LocalSettings.Values.ContainsKey(BackgroundSynchronizationLock)
|
|
||||||
&& ApplicationData.Current.LocalSettings.Values[BackgroundSynchronizationLock] is bool boolValue && boolValue;
|
|
||||||
|
|
||||||
public async Task RunBackgroundSynchronizationAsync(BackgroundSynchronizationReason reason)
|
|
||||||
{
|
|
||||||
Log.Information($"{reason} background synchronization is kicked in.");
|
|
||||||
|
|
||||||
// This should never crash.
|
|
||||||
// We might be in-process or out-of-process.
|
|
||||||
|
|
||||||
//if (IsBackgroundSynchronizationLocked())
|
|
||||||
//{
|
|
||||||
// Log.Warning("Background synchronization is locked. Hence another background synchronization is canceled.");
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
CreateLock();
|
|
||||||
|
|
||||||
var accounts = await _accountService.GetAccountsAsync();
|
|
||||||
|
|
||||||
foreach (var account in accounts)
|
|
||||||
{
|
|
||||||
// We can't sync broken account.
|
|
||||||
if (account.AttentionReason != AccountAttentionReason.None)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
// We can't synchronize without system folder setup is done.
|
|
||||||
//var isSystemFolderSetupDone = await _folderService.CheckSystemFolderSetupDoneAsync(account.Id);
|
|
||||||
|
|
||||||
//// No need to throw here. It's a background process.
|
|
||||||
//if (!isSystemFolderSetupDone)
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
var synchronizer = _winoSynchronizerFactory.GetAccountSynchronizer(account.Id);
|
|
||||||
|
|
||||||
if (synchronizer.State != AccountSynchronizerState.Idle)
|
|
||||||
{
|
|
||||||
Log.Information("Skipping background synchronization for {Name} since current state is {State}", synchronizer.Account.Name, synchronizer.State);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await HandleSynchronizationAsync(synchronizer, reason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error($"[BackgroundSynchronization] Failed with message {ex.Message}");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
ReleaseLock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task HandleSynchronizationAsync(IBaseSynchronizer synchronizer, BackgroundSynchronizationReason reason)
|
|
||||||
{
|
|
||||||
if (synchronizer.State != AccountSynchronizerState.Idle) return;
|
|
||||||
|
|
||||||
var account = synchronizer.Account;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// SessionConnected will do Full synchronization for logon, Timer task will do Inbox only.
|
|
||||||
|
|
||||||
var syncType = reason == BackgroundSynchronizationReason.SessionConnected ? SynchronizationType.Full : SynchronizationType.Inbox;
|
|
||||||
|
|
||||||
var options = new SynchronizationOptions()
|
|
||||||
{
|
|
||||||
AccountId = account.Id,
|
|
||||||
Type = syncType,
|
|
||||||
};
|
|
||||||
|
|
||||||
await synchronizer.SynchronizeAsync(options);
|
|
||||||
}
|
|
||||||
catch (AuthenticationAttentionException authenticationAttentionException)
|
|
||||||
{
|
|
||||||
Log.Error(authenticationAttentionException, $"[BackgroundSync] Invalid credentials for account {account.Address}");
|
|
||||||
|
|
||||||
account.AttentionReason = AccountAttentionReason.InvalidCredentials;
|
|
||||||
await _accountService.UpdateAccountAsync(account);
|
|
||||||
}
|
|
||||||
catch (SystemFolderConfigurationMissingException configMissingException)
|
|
||||||
{
|
|
||||||
Log.Error(configMissingException, $"[BackgroundSync] Missing system folder configuration for account {account.Address}");
|
|
||||||
|
|
||||||
account.AttentionReason = AccountAttentionReason.MissingSystemFolderConfiguration;
|
|
||||||
await _accountService.UpdateAccountAsync(account);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error(ex, "[BackgroundSync] Synchronization failed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +1,36 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using Windows.ApplicationModel;
|
using Windows.ApplicationModel;
|
||||||
using Windows.ApplicationModel.AppService;
|
using Windows.ApplicationModel.AppService;
|
||||||
using Windows.Foundation.Metadata;
|
using Windows.Foundation.Metadata;
|
||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Interfaces;
|
||||||
|
using Wino.Messaging;
|
||||||
|
using Wino.Messaging.Enums;
|
||||||
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.UWP.Services
|
namespace Wino.Core.UWP.Services
|
||||||
{
|
{
|
||||||
public partial class WinoServerConnectionManager : ObservableObject, IWinoServerConnectionManager<AppServiceConnection>
|
public class WinoServerConnectionManager : IWinoServerConnectionManager<AppServiceConnection>
|
||||||
{
|
{
|
||||||
|
private WinoServerConnectionStatus status;
|
||||||
|
|
||||||
|
public WinoServerConnectionStatus Status
|
||||||
|
{
|
||||||
|
get { return status; }
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
status = value;
|
||||||
|
StatusChanged?.Invoke(this, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private AppServiceConnection _connection;
|
private AppServiceConnection _connection;
|
||||||
|
|
||||||
|
public event EventHandler<WinoServerConnectionStatus> StatusChanged;
|
||||||
|
|
||||||
public AppServiceConnection Connection
|
public AppServiceConnection Connection
|
||||||
{
|
{
|
||||||
get { return _connection; }
|
get { return _connection; }
|
||||||
@@ -40,9 +58,6 @@ namespace Wino.Core.UWP.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
private WinoServerConnectionStatus _status;
|
|
||||||
|
|
||||||
public async Task<bool> ConnectAsync()
|
public async Task<bool> ConnectAsync()
|
||||||
{
|
{
|
||||||
if (Status == WinoServerConnectionStatus.Connected) return true;
|
if (Status == WinoServerConnectionStatus.Connected) return true;
|
||||||
@@ -87,12 +102,98 @@ namespace Wino.Core.UWP.Services
|
|||||||
|
|
||||||
private void ServerMessageReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
|
private void ServerMessageReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
|
||||||
{
|
{
|
||||||
// TODO: Handle server messsages.
|
if (args.Request.Message.TryGetValue(MessageConstants.MessageTypeKey, out object messageTypeObject) && messageTypeObject is int messageTypeInt)
|
||||||
|
{
|
||||||
|
var messageType = (MessageType)messageTypeInt;
|
||||||
|
|
||||||
|
if (args.Request.Message.TryGetValue(MessageConstants.MessageDataKey, out object messageDataObject) && messageDataObject is string messageJson)
|
||||||
|
{
|
||||||
|
switch (messageType)
|
||||||
|
{
|
||||||
|
case MessageType.UIMessage:
|
||||||
|
if (args.Request.Message.TryGetValue(MessageConstants.MessageDataTypeKey, out object dataTypeObject) && dataTypeObject is string dataTypeName)
|
||||||
|
{
|
||||||
|
HandleUIMessage(messageJson, dataTypeName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new ArgumentException("Message data type is missing.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MessageType.ServerAction:
|
||||||
|
HandleServerAction(messageJson);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleServerAction(string messageJson)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks IServerMessage objects and delegate it to Messenger for UI to process.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageJson">Message data in json format.</param>
|
||||||
|
private void HandleUIMessage(string messageJson, string typeName)
|
||||||
|
{
|
||||||
|
switch (typeName)
|
||||||
|
{
|
||||||
|
case nameof(MailAddedMessage):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<MailAddedMessage>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(MailDownloadedMessage):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<MailDownloadedMessage>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(MailRemovedMessage):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<MailRemovedMessage>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(MailUpdatedMessage):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<MailUpdatedMessage>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(AccountCreatedMessage):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<AccountCreatedMessage>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(AccountRemovedMessage):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<AccountRemovedMessage>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(AccountUpdatedMessage):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<AccountUpdatedMessage>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(DraftCreated):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<DraftCreated>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(DraftFailed):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<DraftFailed>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(DraftMapped):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<DraftMapped>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(FolderRenamed):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<FolderRenamed>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(FolderSynchronizationEnabled):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<FolderSynchronizationEnabled>(messageJson));
|
||||||
|
break;
|
||||||
|
case nameof(MergedInboxRenamed):
|
||||||
|
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize<MergedInboxRenamed>(messageJson));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Invalid data type name passed to client.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ServerDisconnected(AppServiceConnection sender, AppServiceClosedEventArgs args)
|
private void ServerDisconnected(AppServiceConnection sender, AppServiceClosedEventArgs args)
|
||||||
{
|
{
|
||||||
// TODO: Handle server disconnection.
|
// TODO: Handle server disconnection.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DisposeConnection()
|
||||||
|
{
|
||||||
|
if (Connection == null) return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,6 @@
|
|||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Services\AppInitializerService.cs" />
|
<Compile Include="Services\AppInitializerService.cs" />
|
||||||
<Compile Include="Services\WinoServerConnectionManager.cs" />
|
<Compile Include="Services\WinoServerConnectionManager.cs" />
|
||||||
<Compile Include="Services\BackgroundSynchronizer.cs" />
|
|
||||||
<Compile Include="Services\BackgroundTaskService.cs" />
|
<Compile Include="Services\BackgroundTaskService.cs" />
|
||||||
<Compile Include="Services\ClipboardService.cs" />
|
<Compile Include="Services\ClipboardService.cs" />
|
||||||
<Compile Include="Services\ConfigurationService.cs" />
|
<Compile Include="Services\ConfigurationService.cs" />
|
||||||
@@ -170,6 +169,10 @@
|
|||||||
<Project>{e6b1632a-8901-41e8-9ddf-6793c7698b0b}</Project>
|
<Project>{e6b1632a-8901-41e8-9ddf-6793c7698b0b}</Project>
|
||||||
<Name>Wino.Core</Name>
|
<Name>Wino.Core</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.csproj">
|
||||||
|
<Project>{0c307d7e-256f-448c-8265-5622a812fbcc}</Project>
|
||||||
|
<Name>Wino.Messaging</Name>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<SDKReference Include="WindowsDesktop, Version=10.0.22621.0">
|
<SDKReference Include="WindowsDesktop, Version=10.0.22621.0">
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ 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.Requests;
|
using Wino.Core.Domain.Models.Requests;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Requests
|
namespace Wino.Core.Requests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ 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.Requests;
|
using Wino.Core.Domain.Models.Requests;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Requests
|
namespace Wino.Core.Requests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using Wino.Core.Domain.Enums;
|
|||||||
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.Requests;
|
using Wino.Core.Domain.Models.Requests;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Requests
|
namespace Wino.Core.Requests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ 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.Requests;
|
using Wino.Core.Domain.Models.Requests;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Requests
|
namespace Wino.Core.Requests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ 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.Requests;
|
using Wino.Core.Domain.Models.Requests;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Requests
|
namespace Wino.Core.Requests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ 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.Requests;
|
using Wino.Core.Domain.Models.Requests;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Requests
|
namespace Wino.Core.Requests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ 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.Requests;
|
using Wino.Core.Domain.Models.Requests;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Requests
|
namespace Wino.Core.Requests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ 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.Requests;
|
using Wino.Core.Domain.Models.Requests;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Requests
|
namespace Wino.Core.Requests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
using Wino.Core.Domain.Models.Requests;
|
using Wino.Core.Domain.Models.Requests;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Requests
|
namespace Wino.Core.Requests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using Wino.Core.Domain.Enums;
|
|||||||
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.Requests;
|
using Wino.Core.Domain.Models.Requests;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Requests
|
namespace Wino.Core.Requests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ using Wino.Core.Domain.Enums;
|
|||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Interfaces;
|
||||||
using Wino.Core.Extensions;
|
using Wino.Core.Extensions;
|
||||||
using Wino.Core.Messages.Accounts;
|
using Wino.Core.Messages.Accounts;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Services
|
namespace Wino.Core.Services
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ using Wino.Core.Domain.Models.MailItem;
|
|||||||
using Wino.Core.Domain.Models.Synchronization;
|
using Wino.Core.Domain.Models.Synchronization;
|
||||||
using Wino.Core.Extensions;
|
using Wino.Core.Extensions;
|
||||||
using Wino.Core.MenuItems;
|
using Wino.Core.MenuItems;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Services
|
namespace Wino.Core.Services
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ using Wino.Core.Domain.Interfaces;
|
|||||||
using Wino.Core.Domain.Models.Comparers;
|
using Wino.Core.Domain.Models.Comparers;
|
||||||
using Wino.Core.Domain.Models.MailItem;
|
using Wino.Core.Domain.Models.MailItem;
|
||||||
using Wino.Core.Extensions;
|
using Wino.Core.Extensions;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Core.Services
|
namespace Wino.Core.Services
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace Wino.Core.Services
|
|||||||
{
|
{
|
||||||
private readonly IWinoRequestProcessor _winoRequestProcessor;
|
private readonly IWinoRequestProcessor _winoRequestProcessor;
|
||||||
private readonly IWinoSynchronizerFactory _winoSynchronizerFactory;
|
private readonly IWinoSynchronizerFactory _winoSynchronizerFactory;
|
||||||
|
|
||||||
private readonly IFolderService _folderService;
|
private readonly IFolderService _folderService;
|
||||||
private readonly IDialogService _dialogService;
|
private readonly IDialogService _dialogService;
|
||||||
private readonly ILogger _logger = Log.ForContext<WinoRequestDelegator>();
|
private readonly ILogger _logger = Log.ForContext<WinoRequestDelegator>();
|
||||||
|
|||||||
@@ -37,6 +37,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
|
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
|
||||||
<ProjectReference Include="..\Wino.Messages\Wino.Messages.csproj" />
|
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ using Wino.Core.Domain.Interfaces;
|
|||||||
using Wino.Core.Domain.Models.Folders;
|
using Wino.Core.Domain.Models.Folders;
|
||||||
using Wino.Core.Domain.Models.Navigation;
|
using Wino.Core.Domain.Models.Navigation;
|
||||||
using Wino.Core.Messages.Navigation;
|
using Wino.Core.Messages.Navigation;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Mail.ViewModels
|
namespace Wino.Mail.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ using Wino.Core.Domain.Models.Synchronization;
|
|||||||
using Wino.Core.Messages.Authorization;
|
using Wino.Core.Messages.Authorization;
|
||||||
using Wino.Core.Messages.Navigation;
|
using Wino.Core.Messages.Navigation;
|
||||||
using Wino.Mail.ViewModels.Data;
|
using Wino.Mail.ViewModels.Data;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Mail.ViewModels
|
namespace Wino.Mail.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ using Wino.Core.Messages.Navigation;
|
|||||||
using Wino.Core.Messages.Shell;
|
using Wino.Core.Messages.Shell;
|
||||||
using Wino.Core.Messages.Synchronization;
|
using Wino.Core.Messages.Synchronization;
|
||||||
using Wino.Core.Services;
|
using Wino.Core.Services;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Mail.ViewModels
|
namespace Wino.Mail.ViewModels
|
||||||
{
|
{
|
||||||
@@ -83,6 +83,9 @@ namespace Wino.Mail.ViewModels
|
|||||||
|
|
||||||
private readonly SemaphoreSlim accountInitFolderUpdateSlim = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim accountInitFolderUpdateSlim = new SemaphoreSlim(1);
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _activeConnectionStatus = WinoServerConnectionStatus.None.ToString();
|
||||||
|
|
||||||
public AppShellViewModel(IDialogService dialogService,
|
public AppShellViewModel(IDialogService dialogService,
|
||||||
IWinoNavigationService navigationService,
|
IWinoNavigationService navigationService,
|
||||||
IWinoSynchronizerFactory synchronizerFactory,
|
IWinoSynchronizerFactory synchronizerFactory,
|
||||||
@@ -104,6 +107,14 @@ namespace Wino.Mail.ViewModels
|
|||||||
StatePersistenceService = statePersistanceService;
|
StatePersistenceService = statePersistanceService;
|
||||||
ServerConnectionManager = serverConnectionManager;
|
ServerConnectionManager = serverConnectionManager;
|
||||||
|
|
||||||
|
ServerConnectionManager.StatusChanged += async (sender, status) =>
|
||||||
|
{
|
||||||
|
await ExecuteUIThread(() =>
|
||||||
|
{
|
||||||
|
ActiveConnectionStatus = status.ToString();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
PreferencesService = preferencesService;
|
PreferencesService = preferencesService;
|
||||||
NavigationService = navigationService;
|
NavigationService = navigationService;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ 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.Folders;
|
||||||
using Wino.Core.Domain.Models.Navigation;
|
using Wino.Core.Domain.Models.Navigation;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Mail.ViewModels
|
namespace Wino.Mail.ViewModels
|
||||||
{
|
{
|
||||||
@@ -71,9 +71,7 @@ namespace Wino.Mail.ViewModels
|
|||||||
protected virtual void OnFolderRenamed(IMailItemFolder mailItemFolder) { }
|
protected virtual void OnFolderRenamed(IMailItemFolder mailItemFolder) { }
|
||||||
protected virtual void OnFolderSynchronizationEnabled(IMailItemFolder mailItemFolder) { }
|
protected virtual void OnFolderSynchronizationEnabled(IMailItemFolder mailItemFolder) { }
|
||||||
|
|
||||||
public void ReportUIChange<TMessage>(TMessage message) where TMessage : class, IServerMessage
|
public void ReportUIChange<TMessage>(TMessage message) where TMessage : class, IServerMessage => Messenger.Send(message);
|
||||||
=> Messenger.Send(message);
|
|
||||||
|
|
||||||
void IRecipient<AccountCreatedMessage>.Receive(AccountCreatedMessage message) => OnAccountCreated(message.Account);
|
void IRecipient<AccountCreatedMessage>.Receive(AccountCreatedMessage message) => OnAccountCreated(message.Account);
|
||||||
void IRecipient<AccountRemovedMessage>.Receive(AccountRemovedMessage message) => OnAccountRemoved(message.Account);
|
void IRecipient<AccountRemovedMessage>.Receive(AccountRemovedMessage message) => OnAccountRemoved(message.Account);
|
||||||
void IRecipient<AccountUpdatedMessage>.Receive(AccountUpdatedMessage message) => OnAccountUpdated(message.Account);
|
void IRecipient<AccountUpdatedMessage>.Receive(AccountUpdatedMessage message) => OnAccountUpdated(message.Account);
|
||||||
|
|||||||
@@ -602,6 +602,8 @@ namespace Wino.Mail.ViewModels
|
|||||||
{
|
{
|
||||||
base.OnMailAdded(addedMail);
|
base.OnMailAdded(addedMail);
|
||||||
|
|
||||||
|
if (addedMail.AssignedAccount == null || addedMail.AssignedFolder == null) return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await listManipulationSemepahore.WaitAsync();
|
await listManipulationSemepahore.WaitAsync();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ using Wino.Core.Domain.Interfaces;
|
|||||||
using Wino.Core.Domain.Models.Navigation;
|
using Wino.Core.Domain.Models.Navigation;
|
||||||
using Wino.Core.Messages.Navigation;
|
using Wino.Core.Messages.Navigation;
|
||||||
using Wino.Mail.ViewModels.Data;
|
using Wino.Mail.ViewModels.Data;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Mail.ViewModels
|
namespace Wino.Mail.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
|
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
|
||||||
<ProjectReference Include="..\Wino.Core\Wino.Core.csproj" />
|
<ProjectReference Include="..\Wino.Core\Wino.Core.csproj" />
|
||||||
<ProjectReference Include="..\Wino.Messages\Wino.Messages.csproj" />
|
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
using System.Diagnostics;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Toolkit.Uwp.Notifications;
|
using Microsoft.Toolkit.Uwp.Notifications;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Windows.ApplicationModel.Activation;
|
using Windows.ApplicationModel.Activation;
|
||||||
using Windows.ApplicationModel.Background;
|
using Windows.ApplicationModel.Background;
|
||||||
using Windows.UI.Notifications;
|
using Windows.UI.Notifications;
|
||||||
using Wino.Core;
|
|
||||||
using Wino.Core.Domain;
|
using Wino.Core.Domain;
|
||||||
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.MailItem;
|
using Wino.Core.Domain.Models.MailItem;
|
||||||
using Wino.Core.Domain.Models.Synchronization;
|
using Wino.Core.Domain.Models.Synchronization;
|
||||||
using Wino.Core.UWP.Services;
|
using Wino.Core.UWP.Services;
|
||||||
using Wino.Services;
|
|
||||||
|
|
||||||
namespace Wino.Activation
|
namespace Wino.Activation
|
||||||
{
|
{
|
||||||
@@ -21,7 +18,6 @@ namespace Wino.Activation
|
|||||||
private const string BackgroundExecutionLogTag = "[BackgroundExecution] ";
|
private const string BackgroundExecutionLogTag = "[BackgroundExecution] ";
|
||||||
|
|
||||||
private readonly IWinoRequestDelegator _winoRequestDelegator;
|
private readonly IWinoRequestDelegator _winoRequestDelegator;
|
||||||
private readonly IBackgroundSynchronizer _backgroundSynchronizer;
|
|
||||||
private readonly INativeAppService _nativeAppService;
|
private readonly INativeAppService _nativeAppService;
|
||||||
private readonly IWinoRequestProcessor _winoRequestProcessor;
|
private readonly IWinoRequestProcessor _winoRequestProcessor;
|
||||||
private readonly IWinoSynchronizerFactory _winoSynchronizerFactory;
|
private readonly IWinoSynchronizerFactory _winoSynchronizerFactory;
|
||||||
@@ -30,14 +26,12 @@ namespace Wino.Activation
|
|||||||
|
|
||||||
BackgroundTaskDeferral _deferral;
|
BackgroundTaskDeferral _deferral;
|
||||||
public BackgroundActivationHandler(IWinoRequestDelegator winoRequestDelegator,
|
public BackgroundActivationHandler(IWinoRequestDelegator winoRequestDelegator,
|
||||||
IBackgroundSynchronizer backgroundSynchronizer,
|
|
||||||
INativeAppService nativeAppService,
|
INativeAppService nativeAppService,
|
||||||
IWinoRequestProcessor winoRequestProcessor,
|
IWinoRequestProcessor winoRequestProcessor,
|
||||||
IWinoSynchronizerFactory winoSynchronizerFactory,
|
IWinoSynchronizerFactory winoSynchronizerFactory,
|
||||||
IMailService mailService)
|
IMailService mailService)
|
||||||
{
|
{
|
||||||
_winoRequestDelegator = winoRequestDelegator;
|
_winoRequestDelegator = winoRequestDelegator;
|
||||||
_backgroundSynchronizer = backgroundSynchronizer;
|
|
||||||
_nativeAppService = nativeAppService;
|
_nativeAppService = nativeAppService;
|
||||||
_winoRequestProcessor = winoRequestProcessor;
|
_winoRequestProcessor = winoRequestProcessor;
|
||||||
_winoSynchronizerFactory = winoSynchronizerFactory;
|
_winoSynchronizerFactory = winoSynchronizerFactory;
|
||||||
@@ -104,18 +98,6 @@ namespace Wino.Activation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (taskName == BackgroundTaskService.BackgroundSynchronizationTimerTaskNameEx)
|
|
||||||
{
|
|
||||||
var watch = new Stopwatch();
|
|
||||||
watch.Start();
|
|
||||||
|
|
||||||
// Run timer based background synchronization.
|
|
||||||
|
|
||||||
await _backgroundSynchronizer.RunBackgroundSynchronizationAsync(BackgroundSynchronizationReason.Timer);
|
|
||||||
|
|
||||||
watch.Stop();
|
|
||||||
Log.Information($"{BackgroundExecutionLogTag}Background synchronization is completed in {watch.Elapsed.TotalSeconds} seconds.");
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.Canceled -= OnBackgroundExecutionCanceled;
|
instance.Canceled -= OnBackgroundExecutionCanceled;
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ namespace Wino
|
|||||||
UnhandledException += OnAppUnhandledException;
|
UnhandledException += OnAppUnhandledException;
|
||||||
EnteredBackground += OnEnteredBackground;
|
EnteredBackground += OnEnteredBackground;
|
||||||
LeavingBackground += OnLeavingBackground;
|
LeavingBackground += OnLeavingBackground;
|
||||||
|
|
||||||
|
Resuming += OnResuming;
|
||||||
Suspending += OnSuspending;
|
Suspending += OnSuspending;
|
||||||
|
|
||||||
Services = ConfigureServices();
|
Services = ConfigureServices();
|
||||||
@@ -87,6 +89,15 @@ namespace Wino
|
|||||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void OnResuming(object sender, object e)
|
||||||
|
{
|
||||||
|
// App Service connection was lost on suspension.
|
||||||
|
// We must restore it.
|
||||||
|
// Server might be running already, but re-launching it will trigger a new connection attempt.
|
||||||
|
|
||||||
|
await _appServiceConnectionManager.ConnectAsync();
|
||||||
|
}
|
||||||
|
|
||||||
private void OnSuspending(object sender, SuspendingEventArgs e)
|
private void OnSuspending(object sender, SuspendingEventArgs e)
|
||||||
{
|
{
|
||||||
var deferral = e.SuspendingOperation.GetDeferral();
|
var deferral = e.SuspendingOperation.GetDeferral();
|
||||||
@@ -328,10 +339,12 @@ namespace Wino
|
|||||||
yield return Services.GetService<FileActivationHandler>();
|
yield return Services.GetService<FileActivationHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnBackgroundTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
|
public async void OnBackgroundTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
|
||||||
{
|
{
|
||||||
Log.Information($"Background task {sender.Task.Name} was canceled. Reason: {reason}");
|
Log.Information($"Background task {sender.Task.Name} was canceled. Reason: {reason}");
|
||||||
|
|
||||||
|
await _appServiceConnectionManager.DisconnectAsync();
|
||||||
|
|
||||||
backgroundTaskDeferral?.Complete();
|
backgroundTaskDeferral?.Complete();
|
||||||
backgroundTaskDeferral = null;
|
backgroundTaskDeferral = null;
|
||||||
|
|
||||||
|
|||||||
@@ -521,7 +521,7 @@
|
|||||||
Padding="14"
|
Padding="14"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
VerticalAlignment="Bottom">
|
VerticalAlignment="Bottom">
|
||||||
<TextBlock Text="{x:Bind ViewModel.ServerConnectionManager.Status, Mode=OneWay}" />
|
<TextBlock Text="{x:Bind ViewModel.ActiveConnectionStatus, Mode=OneWay}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</muxc:NavigationView>
|
</muxc:NavigationView>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ using Wino.Core.Messages.Shell;
|
|||||||
using Wino.Core.Messages.Synchronization;
|
using Wino.Core.Messages.Synchronization;
|
||||||
using Wino.Core.UWP.Extensions;
|
using Wino.Core.UWP.Extensions;
|
||||||
using Wino.Dialogs;
|
using Wino.Dialogs;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Services
|
namespace Wino.Services
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using Windows.UI.Xaml.Navigation;
|
|||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
using Wino.Core.Messages.Navigation;
|
using Wino.Core.Messages.Navigation;
|
||||||
using Wino.Mail.ViewModels.Data;
|
using Wino.Mail.ViewModels.Data;
|
||||||
using Wino.Messages.Server;
|
using Wino.Messaging.Server;
|
||||||
using Wino.Views.Abstract;
|
using Wino.Views.Abstract;
|
||||||
using Wino.Views.Account;
|
using Wino.Views.Account;
|
||||||
using Wino.Views.Settings;
|
using Wino.Views.Settings;
|
||||||
|
|||||||
@@ -801,9 +801,9 @@
|
|||||||
<Project>{d62f1c03-da57-4709-a640-0283296a8e66}</Project>
|
<Project>{d62f1c03-da57-4709-a640-0283296a8e66}</Project>
|
||||||
<Name>Wino.Mail.ViewModels</Name>
|
<Name>Wino.Mail.ViewModels</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\Wino.Messages\Wino.Messages.csproj">
|
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.csproj">
|
||||||
<Project>{0c307d7e-256f-448c-8265-5622a812fbcc}</Project>
|
<Project>{0c307d7e-256f-448c-8265-5622a812fbcc}</Project>
|
||||||
<Name>Wino.Messages</Name>
|
<Name>Wino.Messaging</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -811,9 +811,7 @@
|
|||||||
<Name>Windows Desktop Extensions for the UWP</Name>
|
<Name>Windows Desktop Extensions for the UWP</Name>
|
||||||
</SDKReference>
|
</SDKReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup />
|
||||||
<Folder Include="Server\" />
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using Wino.Core.Domain.Models.MailItem;
|
using Wino.Core.Domain.Models.MailItem;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Accounts
|
namespace Wino.Messaging.Client.Accounts
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When menu item for the account is requested to be extended.
|
/// When menu item for the account is requested to be extended.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Accounts
|
namespace Wino.Messaging.Client.Accounts
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Emitted when account menu items are reordered.
|
/// Emitted when account menu items are reordered.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Accounts
|
namespace Wino.Messaging.Client.Accounts
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When a full menu refresh for accounts menu is requested.
|
/// When a full menu refresh for accounts menu is requested.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Authorization
|
namespace Wino.Messaging.Client.Authorization
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When Google authentication makes a callback to the app via protocol activation to the app.
|
/// When Google authentication makes a callback to the app via protocol activation to the app.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When rendered html is requested to cancel.
|
/// When rendered html is requested to cancel.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When reset all mail selections requested.
|
/// When reset all mail selections requested.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using Wino.Core.Domain.Models.Reader;
|
using Wino.Core.Domain.Models.Reader;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When a new composing requested.
|
/// When a new composing requested.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When rendering frame should be disposed.
|
/// When rendering frame should be disposed.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When existing a new html is requested to be rendered due to mail selection or signature.
|
/// When existing a new html is requested to be rendered due to mail selection or signature.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When IMAP setup dialog requestes back breadcrumb navigation.
|
/// When IMAP setup dialog requestes back breadcrumb navigation.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When user asked to dismiss IMAP setup dialog.
|
/// When user asked to dismiss IMAP setup dialog.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When IMAP setup dialog breadcrumb navigation requested.
|
/// When IMAP setup dialog breadcrumb navigation requested.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When a IMailItem needs to be navigated (or selected)
|
/// When a IMailItem needs to be navigated (or selected)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Interfaces;
|
||||||
using Wino.Core.Domain.Models.Navigation;
|
using Wino.Core.Domain.Models.Navigation;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Selects the given FolderMenuItem in the shell folders list.
|
/// Selects the given FolderMenuItem in the shell folders list.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
public record RefreshUnreadCountsMessage(Guid AccountId);
|
public record RefreshUnreadCountsMessage(Guid AccountId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When mail save as PDF requested.
|
/// When mail save as PDF requested.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Mails
|
namespace Wino.Messaging.Client.Mails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When selected mail count is changed.
|
/// When selected mail count is changed.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Navigation
|
namespace Wino.Messaging.Client.Navigation
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When back navigation is requested for breadcrumb pages.
|
/// When back navigation is requested for breadcrumb pages.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Navigation
|
namespace Wino.Messaging.Client.Navigation
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When Breadcrumb control navigation requested.
|
/// When Breadcrumb control navigation requested.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Navigation
|
namespace Wino.Messaging.Client.Navigation
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Navigates to settings page.
|
/// Navigates to settings page.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Shell
|
namespace Wino.Messaging.Client.Shell
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When the application theme changed.
|
/// When the application theme changed.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Shell
|
namespace Wino.Messaging.Client.Shell
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When
|
/// When
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Shell
|
namespace Wino.Messaging.Client.Shell
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For displaying right sliding notification message in shell.
|
/// For displaying right sliding notification message in shell.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Shell
|
namespace Wino.Messaging.Client.Shell
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When application language is updated.
|
/// When application language is updated.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Shell
|
namespace Wino.Messaging.Client.Shell
|
||||||
{
|
{
|
||||||
public class MailtoProtocolMessageRequested { }
|
public class MailtoProtocolMessageRequested { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Shell
|
namespace Wino.Messaging.Client.Shell
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When navigation pane mode is changed.
|
/// When navigation pane mode is changed.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Wino.Messages.Client.Shell
|
namespace Wino.Messaging.Client.Shell
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When reading mail state or reader pane narrowed state is changed.
|
/// When reading mail state or reader pane narrowed state is changed.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Synchronization
|
namespace Wino.Messaging.Client.Synchronization
|
||||||
{
|
{
|
||||||
public record AccountSynchronizationCompleted(Guid AccountId, SynchronizationCompletedState Result, Guid? SynchronizationTrackingId);
|
public record AccountSynchronizationCompleted(Guid AccountId, SynchronizationCompletedState Result, Guid? SynchronizationTrackingId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Interfaces;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Synchronization
|
namespace Wino.Messaging.Client.Synchronization
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Emitted when synchronizer state is updated.
|
/// Emitted when synchronizer state is updated.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using Wino.Core.Domain.Models.Synchronization;
|
using Wino.Core.Domain.Models.Synchronization;
|
||||||
|
|
||||||
namespace Wino.Messages.Client.Synchronization
|
namespace Wino.Messaging.Client.Synchronization
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Triggers a new synchronization if possible.
|
/// Triggers a new synchronization if possible.
|
||||||
|
|||||||
8
Wino.Messages/Enums/MessageType.cs
Normal file
8
Wino.Messages/Enums/MessageType.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Wino.Messaging.Enums
|
||||||
|
{
|
||||||
|
public enum MessageType
|
||||||
|
{
|
||||||
|
UIMessage, // For database changes that needs to be reflected in the UI.
|
||||||
|
ServerAction, //
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Wino.Messages/MessageConstants.cs
Normal file
9
Wino.Messages/MessageConstants.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Wino.Messaging
|
||||||
|
{
|
||||||
|
public static class MessageConstants
|
||||||
|
{
|
||||||
|
public const string MessageTypeKey = "MessageType";
|
||||||
|
public const string MessageDataKey = "MessageData";
|
||||||
|
public const string MessageDataTypeKey = "MessageDataType";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record AccountCreatedMessage(MailAccount Account) : IServerMessage;
|
public record AccountCreatedMessage(MailAccount Account) : ServerMessageBase<AccountCreatedMessage>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record AccountRemovedMessage(MailAccount Account) : IServerMessage;
|
public record AccountRemovedMessage(MailAccount Account) : ServerMessageBase<AccountRemovedMessage>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record AccountUpdatedMessage(MailAccount Account) : IServerMessage;
|
public record AccountUpdatedMessage(MailAccount Account) : ServerMessageBase<AccountUpdatedMessage>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record DraftCreated(MailCopy DraftMail, MailAccount Account) : IServerMessage;
|
public record DraftCreated(MailCopy DraftMail, MailAccount Account) : ServerMessageBase<DraftCreated>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record DraftFailed(MailCopy DraftMail, MailAccount Account) : IServerMessage;
|
public record DraftFailed(MailCopy DraftMail, MailAccount Account) : ServerMessageBase<DraftFailed>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using Wino.Core.Domain.Interfaces;
|
namespace Wino.Messaging.Server
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
|
||||||
{
|
{
|
||||||
public record DraftMapped(string LocalDraftCopyId, string RemoteDraftCopyId) : IServerMessage;
|
public record DraftMapped(string LocalDraftCopyId, string RemoteDraftCopyId) : ServerMessageBase<DraftMapped>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Models.Folders;
|
||||||
using Wino.Core.Domain.Models.Folders;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record FolderRenamed(IMailItemFolder MailItemFolder) : IServerMessage;
|
public record FolderRenamed(IMailItemFolder MailItemFolder) : ServerMessageBase<FolderRenamed>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Models.Folders;
|
||||||
using Wino.Core.Domain.Models.Folders;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record FolderSynchronizationEnabled(IMailItemFolder MailItemFolder) : IServerMessage;
|
public record FolderSynchronizationEnabled(IMailItemFolder MailItemFolder) : ServerMessageBase<FolderSynchronizationEnabled>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record MailAddedMessage(MailCopy AddedMail) : IServerMessage;
|
public record MailAddedMessage(MailCopy AddedMail) : ServerMessageBase<MailAddedMessage>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record MailDownloadedMessage(MailCopy DownloadedMail) : IServerMessage;
|
public record MailDownloadedMessage(MailCopy DownloadedMail) : ServerMessageBase<MailDownloadedMessage>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record MailRemovedMessage(MailCopy RemovedMail) : IServerMessage;
|
public record MailRemovedMessage(MailCopy RemovedMail) : ServerMessageBase<MailRemovedMessage>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record MailUpdatedMessage(MailCopy UpdatedMail) : IServerMessage;
|
public record MailUpdatedMessage(MailCopy UpdatedMail) : ServerMessageBase<MailUpdatedMessage>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Wino.Core.Domain.Interfaces;
|
|
||||||
|
|
||||||
namespace Wino.Messages.Server
|
namespace Wino.Messaging.Server
|
||||||
{
|
{
|
||||||
public record MergedInboxRenamed(Guid MergedInboxId, string NewName) : IServerMessage;
|
public record MergedInboxRenamed(Guid MergedInboxId, string NewName) : ServerMessageBase<MergedInboxRenamed>;
|
||||||
}
|
}
|
||||||
|
|||||||
6
Wino.Messages/Server/ServerMessageBase.cs
Normal file
6
Wino.Messages/Server/ServerMessageBase.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
using Wino.Core.Domain.Interfaces;
|
||||||
|
|
||||||
|
namespace Wino.Messaging.Server
|
||||||
|
{
|
||||||
|
public record ServerMessageBase<T> : IServerMessage { }
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
<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="System.Text.Json" Version="8.0.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,18 +1,70 @@
|
|||||||
using System.Windows;
|
using System.Threading;
|
||||||
|
using System.Windows;
|
||||||
using H.NotifyIcon;
|
using H.NotifyIcon;
|
||||||
|
|
||||||
namespace Wino.Server
|
namespace Wino.Server
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Single instance Wino Server.
|
||||||
|
/// Instancing is done using Mutex.
|
||||||
|
/// App will not start if another instance is already running.
|
||||||
|
/// App will let running server know that server execution is triggered, which will
|
||||||
|
/// led server to start new connection to requesting UWP app.
|
||||||
|
/// </summary>
|
||||||
public partial class App : Application
|
public partial class App : Application
|
||||||
{
|
{
|
||||||
|
private const string WinoServerAppName = "Wino.Server";
|
||||||
|
private const string WinoServerActiatedName = "Wino.Server.Activated";
|
||||||
|
|
||||||
private TaskbarIcon? notifyIcon;
|
private TaskbarIcon? notifyIcon;
|
||||||
|
private static Mutex _mutex = null;
|
||||||
|
private EventWaitHandle _eventWaitHandle;
|
||||||
|
|
||||||
protected override void OnStartup(StartupEventArgs e)
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnStartup(e);
|
bool isCreatedNew;
|
||||||
|
|
||||||
notifyIcon = (TaskbarIcon)FindResource("NotifyIcon");
|
_mutex = new Mutex(true, WinoServerAppName, out isCreatedNew);
|
||||||
notifyIcon.ForceCreate(enablesEfficiencyMode: true);
|
_eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, WinoServerActiatedName);
|
||||||
|
|
||||||
|
if (isCreatedNew)
|
||||||
|
{
|
||||||
|
// Spawn a thread which will be waiting for our event
|
||||||
|
var thread = new Thread(() =>
|
||||||
|
{
|
||||||
|
while (_eventWaitHandle.WaitOne())
|
||||||
|
{
|
||||||
|
if (notifyIcon == null) return;
|
||||||
|
|
||||||
|
Current.Dispatcher.BeginInvoke(() =>
|
||||||
|
{
|
||||||
|
if (notifyIcon.DataContext is TrayIconViewModel trayIconViewModel)
|
||||||
|
{
|
||||||
|
trayIconViewModel.Reconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// It is important mark it as background otherwise it will prevent app from exiting.
|
||||||
|
thread.IsBackground = true;
|
||||||
|
|
||||||
|
thread.Start();
|
||||||
|
|
||||||
|
base.OnStartup(e);
|
||||||
|
|
||||||
|
// Create taskbar icon for the new server.
|
||||||
|
notifyIcon = (TaskbarIcon)FindResource("NotifyIcon");
|
||||||
|
notifyIcon.ForceCreate(enablesEfficiencyMode: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Notify other instance so it could bring itself to foreground.
|
||||||
|
_eventWaitHandle.Set();
|
||||||
|
|
||||||
|
// Terminate this instance.
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnExit(ExitEventArgs e)
|
protected override void OnExit(ExitEventArgs e)
|
||||||
|
|||||||
@@ -1,12 +1,21 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Windows.ApplicationModel;
|
using Windows.ApplicationModel;
|
||||||
using Windows.ApplicationModel.AppService;
|
using Windows.ApplicationModel.AppService;
|
||||||
using Windows.Foundation.Collections;
|
using Windows.Foundation.Collections;
|
||||||
|
using Wino.Core.Domain.Entities;
|
||||||
|
using Wino.Core.Domain.Interfaces;
|
||||||
|
using Wino.Messaging;
|
||||||
|
using Wino.Messaging.Enums;
|
||||||
|
using Wino.Messaging.Server;
|
||||||
|
|
||||||
namespace Wino.Server
|
namespace Wino.Server
|
||||||
{
|
{
|
||||||
public class ServerContext
|
public class ServerContext
|
||||||
{
|
{
|
||||||
|
private static object connectionLock = new object();
|
||||||
|
|
||||||
private AppServiceConnection connection = null;
|
private AppServiceConnection connection = null;
|
||||||
|
|
||||||
public ServerContext()
|
public ServerContext()
|
||||||
@@ -14,15 +23,33 @@ namespace Wino.Server
|
|||||||
InitializeAppServiceConnection();
|
InitializeAppServiceConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetAppPackagFamilyName()
|
||||||
|
{
|
||||||
|
// If running as a standalone app, Package will throw exception.
|
||||||
|
// Return hardcoded value for debugging purposes.
|
||||||
|
// Connection will not be available in this case.
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Package.Current.Id.FamilyName;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return "Debug.Wino.Server.FamilyName";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Open connection to UWP app service
|
/// Open connection to UWP app service
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async void InitializeAppServiceConnection()
|
public async void InitializeAppServiceConnection()
|
||||||
{
|
{
|
||||||
|
if (connection != null) DisposeConnection();
|
||||||
|
|
||||||
connection = new AppServiceConnection
|
connection = new AppServiceConnection
|
||||||
{
|
{
|
||||||
AppServiceName = "WinoInteropService",
|
AppServiceName = "WinoInteropService",
|
||||||
PackageFamilyName = Package.Current.Id.FamilyName
|
PackageFamilyName = GetAppPackagFamilyName()
|
||||||
};
|
};
|
||||||
|
|
||||||
connection.RequestReceived += OnWinRTMessageReceived;
|
connection.RequestReceived += OnWinRTMessageReceived;
|
||||||
@@ -33,13 +60,33 @@ namespace Wino.Server
|
|||||||
if (status != AppServiceConnectionStatus.Success)
|
if (status != AppServiceConnectionStatus.Success)
|
||||||
{
|
{
|
||||||
// TODO: Handle connection error
|
// TODO: Handle connection error
|
||||||
|
|
||||||
|
DisposeConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void SendMessage()
|
public Task SendTestMessageAsync()
|
||||||
{
|
{
|
||||||
var set = new ValueSet();
|
var message = new MailAddedMessage(new MailCopy());
|
||||||
set.Add("Hello", "World");
|
return SendMessageAsync(MessageType.UIMessage, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SendMessageAsync(MessageType messageType, object message)
|
||||||
|
{
|
||||||
|
if (connection == null) return;
|
||||||
|
|
||||||
|
if (message is not IServerMessage serverMessage)
|
||||||
|
throw new ArgumentException("Server message must be a type of IServerMessage");
|
||||||
|
|
||||||
|
string json = JsonSerializer.Serialize(message);
|
||||||
|
|
||||||
|
var set = new ValueSet
|
||||||
|
{
|
||||||
|
{ MessageConstants.MessageTypeKey, (int)messageType },
|
||||||
|
{ MessageConstants.MessageDataKey, json },
|
||||||
|
{ MessageConstants.MessageDataTypeKey, message.GetType().Name }
|
||||||
|
};
|
||||||
|
|
||||||
await connection.SendMessageAsync(set);
|
await connection.SendMessageAsync(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,12 +94,30 @@ namespace Wino.Server
|
|||||||
{
|
{
|
||||||
// TODO: Handle connection closed.
|
// TODO: Handle connection closed.
|
||||||
|
|
||||||
// UWP app might've been terminated.
|
// UWP app might've been terminated or suspended.
|
||||||
|
// At this point, we must keep active synchronizations going, but connection is lost.
|
||||||
|
// As long as this process is alive, database will be kept updated, but no messages will be sent.
|
||||||
|
|
||||||
|
DisposeConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnWinRTMessageReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
|
private void OnWinRTMessageReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
|
||||||
{
|
{
|
||||||
// TODO: Handle incoming messages from UWP/WINUI Application.
|
// TODO: Handle incoming messages from UWP/WINUI Application.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DisposeConnection()
|
||||||
|
{
|
||||||
|
lock (connectionLock)
|
||||||
|
{
|
||||||
|
if (connection == null) return;
|
||||||
|
|
||||||
|
connection.RequestReceived -= OnWinRTMessageReceived;
|
||||||
|
connection.ServiceClosed -= OnConnectionClosed;
|
||||||
|
|
||||||
|
connection.Dispose();
|
||||||
|
connection = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Wino.Server
|
|||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
public void LaunchWino()
|
public void LaunchWino()
|
||||||
{
|
{
|
||||||
_context.SendMessage();
|
_context.SendTestMessageAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -24,5 +24,7 @@ namespace Wino.Server
|
|||||||
|
|
||||||
Application.Current.Shutdown();
|
Application.Current.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Reconnect() => _context.InitializeAppServiceConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
|
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
|
||||||
<ProjectReference Include="..\Wino.Core\Wino.Core.csproj" />
|
<ProjectReference Include="..\Wino.Core\Wino.Core.csproj" />
|
||||||
<ProjectReference Include="..\Wino.Messages\Wino.Messages.csproj" />
|
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
4
Wino.sln
4
Wino.sln
@@ -15,11 +15,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.BackgroundTasks", "Win
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Mail.ViewModels", "Wino.Mail.ViewModels\Wino.Mail.ViewModels.csproj", "{D62F1C03-DA57-4709-A640-0283296A8E66}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Mail.ViewModels", "Wino.Mail.ViewModels\Wino.Mail.ViewModels.csproj", "{D62F1C03-DA57-4709-A640-0283296A8E66}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Messages", "Wino.Messages\Wino.Messages.csproj", "{0C307D7E-256F-448C-8265-5622A812FBCC}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Messaging", "Wino.Messages\Wino.Messaging.csproj", "{0C307D7E-256F-448C-8265-5622A812FBCC}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Wino.Packaging", "Wino.Packaging\Wino.Packaging.wapproj", "{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}"
|
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Wino.Packaging", "Wino.Packaging\Wino.Packaging.wapproj", "{760F5F31-8EE3-4B83-80F3-0E4FFBCC737C}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Server", "Wino.Server\Wino.Server.csproj", "{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wino.Server", "Wino.Server\Wino.Server.csproj", "{3D1942E5-1A3B-4062-B4BB-156A40DA47FE}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
|||||||
Reference in New Issue
Block a user