Remove connection manager.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -1,255 +0,0 @@
|
||||
using System.Windows.Input;
|
||||
using Windows.Foundation;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.WinUI.Controls;
|
||||
|
||||
public sealed partial class WinoAppTitleBar : UserControl
|
||||
{
|
||||
public event TypedEventHandler<WinoAppTitleBar, RoutedEventArgs> BackButtonClicked;
|
||||
|
||||
public static readonly DependencyProperty IsRenderingPaneVisibleProperty = DependencyProperty.Register(nameof(IsRenderingPaneVisible), typeof(bool), typeof(WinoAppTitleBar), new PropertyMetadata(false, OnDrawingPropertyChanged));
|
||||
public static readonly DependencyProperty IsReaderNarrowedProperty = DependencyProperty.Register(nameof(IsReaderNarrowed), typeof(bool), typeof(WinoAppTitleBar), new PropertyMetadata(false, OnIsReaderNarrowedChanged));
|
||||
public static readonly DependencyProperty IsBackButtonVisibleProperty = DependencyProperty.Register(nameof(IsBackButtonVisible), typeof(bool), typeof(WinoAppTitleBar), new PropertyMetadata(false, OnDrawingPropertyChanged));
|
||||
public static readonly DependencyProperty OpenPaneLengthProperty = DependencyProperty.Register(nameof(OpenPaneLength), typeof(double), typeof(WinoAppTitleBar), new PropertyMetadata(0d, OnDrawingPropertyChanged));
|
||||
public static readonly DependencyProperty IsNavigationPaneOpenProperty = DependencyProperty.Register(nameof(IsNavigationPaneOpen), typeof(bool), typeof(WinoAppTitleBar), new PropertyMetadata(false, OnDrawingPropertyChanged));
|
||||
public static readonly DependencyProperty NavigationViewDisplayModeProperty = DependencyProperty.Register(nameof(NavigationViewDisplayMode), typeof(Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode), typeof(WinoAppTitleBar), new PropertyMetadata(Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Compact, OnDrawingPropertyChanged));
|
||||
public static readonly DependencyProperty ShellFrameContentProperty = DependencyProperty.Register(nameof(ShellFrameContent), typeof(UIElement), typeof(WinoAppTitleBar), new PropertyMetadata(null, OnDrawingPropertyChanged));
|
||||
public static readonly DependencyProperty SystemReservedProperty = DependencyProperty.Register(nameof(SystemReserved), typeof(double), typeof(WinoAppTitleBar), new PropertyMetadata(0, OnDrawingPropertyChanged));
|
||||
public static readonly DependencyProperty CoreWindowTextProperty = DependencyProperty.Register(nameof(CoreWindowText), typeof(string), typeof(WinoAppTitleBar), new PropertyMetadata(string.Empty, OnDrawingPropertyChanged));
|
||||
public static readonly DependencyProperty ReadingPaneLengthProperty = DependencyProperty.Register(nameof(ReadingPaneLength), typeof(double), typeof(WinoAppTitleBar), new PropertyMetadata(420d, OnDrawingPropertyChanged));
|
||||
public static readonly DependencyProperty ConnectionStatusProperty = DependencyProperty.Register(nameof(ConnectionStatus), typeof(WinoServerConnectionStatus), typeof(WinoAppTitleBar), new PropertyMetadata(WinoServerConnectionStatus.None, new PropertyChangedCallback(OnConnectionStatusChanged)));
|
||||
public static readonly DependencyProperty ReconnectCommandProperty = DependencyProperty.Register(nameof(ReconnectCommand), typeof(ICommand), typeof(WinoAppTitleBar), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty ShrinkShellContentOnExpansionProperty = DependencyProperty.Register(nameof(ShrinkShellContentOnExpansion), typeof(bool), typeof(WinoAppTitleBar), new PropertyMetadata(true));
|
||||
public static readonly DependencyProperty IsDragAreaProperty = DependencyProperty.Register(nameof(IsDragArea), typeof(bool), typeof(WinoAppTitleBar), new PropertyMetadata(false, new PropertyChangedCallback(OnIsDragAreaChanged)));
|
||||
public static readonly DependencyProperty IsShellFrameContentVisibleProperty = DependencyProperty.Register(nameof(IsShellFrameContentVisible), typeof(bool), typeof(WinoAppTitleBar), new PropertyMetadata(true));
|
||||
public static readonly DependencyProperty IsMenuButtonVisibleProperty = DependencyProperty.Register(nameof(IsMenuButtonVisible), typeof(bool), typeof(WinoAppTitleBar), new PropertyMetadata(true));
|
||||
|
||||
public bool IsShellFrameContentVisible
|
||||
{
|
||||
get { return (bool)GetValue(IsShellFrameContentVisibleProperty); }
|
||||
set { SetValue(IsShellFrameContentVisibleProperty, value); }
|
||||
}
|
||||
|
||||
public ICommand ReconnectCommand
|
||||
{
|
||||
get { return (ICommand)GetValue(ReconnectCommandProperty); }
|
||||
set { SetValue(ReconnectCommandProperty, value); }
|
||||
}
|
||||
|
||||
public WinoServerConnectionStatus ConnectionStatus
|
||||
{
|
||||
get { return (WinoServerConnectionStatus)GetValue(ConnectionStatusProperty); }
|
||||
set { SetValue(ConnectionStatusProperty, value); }
|
||||
}
|
||||
|
||||
public string CoreWindowText
|
||||
{
|
||||
get { return (string)GetValue(CoreWindowTextProperty); }
|
||||
set { SetValue(CoreWindowTextProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsDragArea
|
||||
{
|
||||
get { return (bool)GetValue(IsDragAreaProperty); }
|
||||
set { SetValue(IsDragAreaProperty, value); }
|
||||
}
|
||||
|
||||
|
||||
public double SystemReserved
|
||||
{
|
||||
get { return (double)GetValue(SystemReservedProperty); }
|
||||
set { SetValue(SystemReservedProperty, value); }
|
||||
}
|
||||
|
||||
public UIElement ShellFrameContent
|
||||
{
|
||||
get { return (UIElement)GetValue(ShellFrameContentProperty); }
|
||||
set { SetValue(ShellFrameContentProperty, value); }
|
||||
}
|
||||
|
||||
public Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode NavigationViewDisplayMode
|
||||
{
|
||||
get { return (Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode)GetValue(NavigationViewDisplayModeProperty); }
|
||||
set { SetValue(NavigationViewDisplayModeProperty, value); }
|
||||
}
|
||||
|
||||
public bool ShrinkShellContentOnExpansion
|
||||
{
|
||||
get { return (bool)GetValue(ShrinkShellContentOnExpansionProperty); }
|
||||
set { SetValue(ShrinkShellContentOnExpansionProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsNavigationPaneOpen
|
||||
{
|
||||
get { return (bool)GetValue(IsNavigationPaneOpenProperty); }
|
||||
set { SetValue(IsNavigationPaneOpenProperty, value); }
|
||||
}
|
||||
|
||||
public double OpenPaneLength
|
||||
{
|
||||
get { return (double)GetValue(OpenPaneLengthProperty); }
|
||||
set { SetValue(OpenPaneLengthProperty, value); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public bool IsMenuButtonVisible
|
||||
{
|
||||
get { return (bool)GetValue(IsMenuButtonVisibleProperty); }
|
||||
set { SetValue(IsMenuButtonVisibleProperty, value); }
|
||||
}
|
||||
|
||||
|
||||
public bool IsBackButtonVisible
|
||||
{
|
||||
get { return (bool)GetValue(IsBackButtonVisibleProperty); }
|
||||
set { SetValue(IsBackButtonVisibleProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsReaderNarrowed
|
||||
{
|
||||
get { return (bool)GetValue(IsReaderNarrowedProperty); }
|
||||
set { SetValue(IsReaderNarrowedProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsRenderingPaneVisible
|
||||
{
|
||||
get { return (bool)GetValue(IsRenderingPaneVisibleProperty); }
|
||||
set { SetValue(IsRenderingPaneVisibleProperty, value); }
|
||||
}
|
||||
|
||||
public double ReadingPaneLength
|
||||
{
|
||||
get { return (double)GetValue(ReadingPaneLengthProperty); }
|
||||
set { SetValue(ReadingPaneLengthProperty, value); }
|
||||
}
|
||||
|
||||
private static void OnIsReaderNarrowedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is WinoAppTitleBar bar)
|
||||
{
|
||||
bar.DrawTitleBar();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnDrawingPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is WinoAppTitleBar bar)
|
||||
{
|
||||
bar.DrawTitleBar();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnConnectionStatusChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is WinoAppTitleBar bar)
|
||||
{
|
||||
bar.UpdateConnectionStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnIsDragAreaChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is WinoAppTitleBar bar)
|
||||
{
|
||||
bar.SetDragArea();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetDragArea()
|
||||
{
|
||||
if (IsDragArea)
|
||||
{
|
||||
Window.Current.SetTitleBar(dragbar);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateConnectionStatus()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void DrawTitleBar()
|
||||
{
|
||||
UpdateLayout();
|
||||
|
||||
CoreWindowTitleTextBlock.Visibility = Visibility.Collapsed;
|
||||
ShellContentContainer.Width = double.NaN;
|
||||
ShellContentContainer.Margin = new Thickness(0, 0, 0, 0);
|
||||
ShellContentContainer.HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
|
||||
EmptySpaceWidth.Width = new GridLength(1, GridUnitType.Star);
|
||||
|
||||
// Menu is not visible.
|
||||
if (NavigationViewDisplayMode == Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Minimal)
|
||||
{
|
||||
|
||||
}
|
||||
else if (NavigationViewDisplayMode == Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Compact)
|
||||
{
|
||||
// Icons are visible.
|
||||
|
||||
if (!IsReaderNarrowed && ShrinkShellContentOnExpansion)
|
||||
{
|
||||
ShellContentContainer.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
ShellContentContainer.Width = ReadingPaneLength;
|
||||
}
|
||||
}
|
||||
else if (NavigationViewDisplayMode == Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Expanded)
|
||||
{
|
||||
if (IsNavigationPaneOpen)
|
||||
{
|
||||
CoreWindowTitleTextBlock.Visibility = Visibility.Visible;
|
||||
|
||||
// LMargin = OpenPaneLength - LeftMenuStackPanel
|
||||
ShellContentContainer.Margin = new Thickness(OpenPaneLength - LeftMenuStackPanel.ActualSize.X, 0, 0, 0);
|
||||
|
||||
if (!IsReaderNarrowed && ShrinkShellContentOnExpansion)
|
||||
{
|
||||
ShellContentContainer.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
ShellContentContainer.Width = ReadingPaneLength;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ShrinkShellContentOnExpansion)
|
||||
{
|
||||
EmptySpaceWidth.Width = new GridLength(ReadingPaneLength, GridUnitType.Pixel);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmptySpaceWidth.Width = new GridLength(ReadingPaneLength, GridUnitType.Star);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WinoAppTitleBar()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void BackClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
BackButtonClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void PaneClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
IsNavigationPaneOpen = !IsNavigationPaneOpen;
|
||||
}
|
||||
|
||||
private void TitlebarSizeChanged(object sender, SizeChangedEventArgs e) => DrawTitleBar();
|
||||
|
||||
private void ReconnectClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Close the popup for reconnect button.
|
||||
ReconnectFlyout.Hide();
|
||||
|
||||
// Execute the reconnect command.
|
||||
ReconnectCommand?.Execute(null);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ public static class CoreUWPContainerSetup
|
||||
{
|
||||
public static void RegisterCoreUWPServices(this IServiceCollection services)
|
||||
{
|
||||
var serverConnectionManager = new WinoServerConnectionManager();
|
||||
var serverConnectionManager = new EmptyWinoServerConnectionManager<AppServiceConnection>();
|
||||
|
||||
services.AddSingleton<IWinoServerConnectionManager>(serverConnectionManager);
|
||||
services.AddSingleton<IWinoServerConnectionManager<AppServiceConnection>>(serverConnectionManager);
|
||||
|
||||
@@ -161,7 +161,7 @@ public static class XamlHelpers
|
||||
|
||||
return Translator.UnknownDateHeader;
|
||||
}
|
||||
public static bool ConnectionStatusEquals(WinoServerConnectionStatus winoServerConnectionStatus, WinoServerConnectionStatus connectionStatus) => winoServerConnectionStatus == connectionStatus;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.WinUI.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Empty implementation of IWinoServerConnectionManager that returns default values.
|
||||
/// This replaces the old AppServiceConnection-based implementation.
|
||||
/// </summary>
|
||||
public class EmptyWinoServerConnectionManager : IWinoServerConnectionManager
|
||||
{
|
||||
public event EventHandler<WinoServerConnectionStatus> StatusChanged { add { } remove { } }
|
||||
|
||||
public WinoServerConnectionStatus Status => WinoServerConnectionStatus.Connected;
|
||||
|
||||
public TaskCompletionSource<bool> ConnectingHandle { get; } = new TaskCompletionSource<bool>();
|
||||
|
||||
public EmptyWinoServerConnectionManager()
|
||||
{
|
||||
ConnectingHandle.SetResult(true);
|
||||
}
|
||||
|
||||
public Task<bool> ConnectAsync()
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
public Task QueueRequestAsync(IRequestBase request, Guid accountId)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<WinoServerResponse<TResponse>> GetResponseAsync<TResponse, TRequestType>(TRequestType clientMessage, CancellationToken cancellationToken = default)
|
||||
where TRequestType : IClientMessage
|
||||
{
|
||||
var response = WinoServerResponse<TResponse>.CreateSuccessResponse(default(TResponse));
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generic empty implementation for typed connection managers.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAppServiceConnection">The connection type (not used in this implementation)</typeparam>
|
||||
public class EmptyWinoServerConnectionManager<TAppServiceConnection> : EmptyWinoServerConnectionManager, IWinoServerConnectionManager<TAppServiceConnection>
|
||||
{
|
||||
public TAppServiceConnection Connection { get; set; }
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -236,12 +236,6 @@ public class PreferencesService(IConfigurationService configurationService) : Ob
|
||||
set => SaveProperty(propertyName: nameof(AutoSelectNextItem), value);
|
||||
}
|
||||
|
||||
public ServerBackgroundMode ServerTerminationBehavior
|
||||
{
|
||||
get => _configurationService.Get(nameof(ServerTerminationBehavior), ServerBackgroundMode.MinimizedTray);
|
||||
set => SaveProperty(propertyName: nameof(ServerTerminationBehavior), value);
|
||||
}
|
||||
|
||||
public string DiagnosticId
|
||||
{
|
||||
get => _configurationService.Get(nameof(DiagnosticId), Guid.NewGuid().ToString());
|
||||
|
||||
@@ -1,369 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Nito.AsyncEx;
|
||||
using Serilog;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.ApplicationModel.AppService;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.Foundation.Metadata;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Requests;
|
||||
using Wino.Core.Domain.Models.Server;
|
||||
using Wino.Core.Integration.Json;
|
||||
using Wino.Messaging;
|
||||
using Wino.Messaging.Client.Connection;
|
||||
using Wino.Messaging.Enums;
|
||||
using Wino.Messaging.Server;
|
||||
using Wino.Messaging.UI;
|
||||
|
||||
namespace Wino.Core.WinUI.Services;
|
||||
|
||||
public class WinoServerConnectionManager :
|
||||
IWinoServerConnectionManager<AppServiceConnection>,
|
||||
IRecipient<WinoServerConnectionEstablished>
|
||||
{
|
||||
private const int ServerConnectionTimeoutMs = 10000;
|
||||
|
||||
public event EventHandler<WinoServerConnectionStatus> StatusChanged;
|
||||
|
||||
public TaskCompletionSource<bool> ConnectingHandle { get; private set; }
|
||||
|
||||
private ILogger Logger => Logger.ForContext<WinoServerConnectionManager>();
|
||||
|
||||
private WinoServerConnectionStatus status;
|
||||
|
||||
public WinoServerConnectionStatus Status
|
||||
{
|
||||
get { return status; }
|
||||
private set
|
||||
{
|
||||
Log.Information("Server connection status changed to {Status}.", value);
|
||||
status = value;
|
||||
StatusChanged?.Invoke(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
private AppServiceConnection _connection;
|
||||
public AppServiceConnection Connection
|
||||
{
|
||||
get { return _connection; }
|
||||
set
|
||||
{
|
||||
if (_connection != null)
|
||||
{
|
||||
_connection.RequestReceived -= ServerMessageReceived;
|
||||
_connection.ServiceClosed -= ServerDisconnected;
|
||||
}
|
||||
|
||||
_connection = value;
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
Status = WinoServerConnectionStatus.Disconnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
value.RequestReceived += ServerMessageReceived;
|
||||
value.ServiceClosed += ServerDisconnected;
|
||||
|
||||
Status = WinoServerConnectionStatus.Connected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly JsonSerializerOptions _jsonSerializerOptions = new()
|
||||
{
|
||||
TypeInfoResolver = new ServerRequestTypeInfoResolver()
|
||||
};
|
||||
|
||||
public WinoServerConnectionManager()
|
||||
{
|
||||
WeakReferenceMessenger.Default.Register(this);
|
||||
}
|
||||
|
||||
public async Task<bool> ConnectAsync()
|
||||
{
|
||||
if (Status == WinoServerConnectionStatus.Connected)
|
||||
{
|
||||
Log.Information("Server is already connected.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Status == WinoServerConnectionStatus.Connecting)
|
||||
{
|
||||
// A connection is already being established at the moment.
|
||||
// No need to run another connection establishment process.
|
||||
// Await the connecting handler if possible.
|
||||
|
||||
if (ConnectingHandle != null)
|
||||
{
|
||||
return await ConnectingHandle.Task;
|
||||
}
|
||||
}
|
||||
|
||||
if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
|
||||
{
|
||||
try
|
||||
{
|
||||
ConnectingHandle = new TaskCompletionSource<bool>();
|
||||
|
||||
Status = WinoServerConnectionStatus.Connecting;
|
||||
|
||||
var connectionCancellationToken = new CancellationTokenSource(TimeSpan.FromMilliseconds(ServerConnectionTimeoutMs));
|
||||
|
||||
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("WinoServer");
|
||||
|
||||
// Connection establishment handler is in App.xaml.cs OnBackgroundActivated.
|
||||
// Once the connection is established, the handler will set the Connection property
|
||||
// and WinoServerConnectionEstablished will be fired by the messenger.
|
||||
|
||||
await ConnectingHandle.Task.WaitAsync(connectionCancellationToken.Token);
|
||||
|
||||
Log.Information("Server connection established successfully.");
|
||||
}
|
||||
catch (OperationCanceledException canceledException)
|
||||
{
|
||||
Log.Error(canceledException, $"Server process did not start in {ServerConnectionTimeoutMs} ms. Operation is canceled.");
|
||||
|
||||
ConnectingHandle?.TrySetException(canceledException);
|
||||
|
||||
Status = WinoServerConnectionStatus.Failed;
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Failed to connect to the server.");
|
||||
|
||||
ConnectingHandle?.TrySetException(ex);
|
||||
|
||||
Status = WinoServerConnectionStatus.Failed;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Information("FullTrustAppContract is not present in the system. Server connection is not possible.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
var isConnectionSuccessfull = await ConnectAsync();
|
||||
|
||||
if (isConnectionSuccessfull)
|
||||
{
|
||||
Log.Information("ServerConnectionManager initialized successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error("ServerConnectionManager initialization failed.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ServerMessageReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
|
||||
{
|
||||
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 not string dataTypeName)
|
||||
throw new ArgumentException("Message data type is missing.");
|
||||
|
||||
HandleUIMessage(messageJson, dataTypeName);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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(messageJson, CommunicationMessagesContext.Default.MailAddedMessage));
|
||||
break;
|
||||
case nameof(MailDownloadedMessage):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.MailDownloadedMessage));
|
||||
break;
|
||||
case nameof(MailRemovedMessage):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.MailRemovedMessage));
|
||||
break;
|
||||
case nameof(MailUpdatedMessage):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.MailUpdatedMessage));
|
||||
break;
|
||||
case nameof(AccountCreatedMessage):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.AccountCreatedMessage));
|
||||
break;
|
||||
case nameof(AccountRemovedMessage):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.AccountRemovedMessage));
|
||||
break;
|
||||
case nameof(AccountUpdatedMessage):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.AccountUpdatedMessage));
|
||||
break;
|
||||
case nameof(DraftCreated):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.DraftCreated));
|
||||
break;
|
||||
case nameof(DraftFailed):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.DraftFailed));
|
||||
break;
|
||||
case nameof(DraftMapped):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.DraftMapped));
|
||||
break;
|
||||
case nameof(FolderRenamed):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.FolderRenamed));
|
||||
break;
|
||||
case nameof(FolderSynchronizationEnabled):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.FolderSynchronizationEnabled));
|
||||
break;
|
||||
case nameof(MergedInboxRenamed):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.MergedInboxRenamed));
|
||||
break;
|
||||
case nameof(AccountSynchronizationCompleted):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.AccountSynchronizationCompleted));
|
||||
break;
|
||||
case nameof(RefreshUnreadCountsMessage):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.RefreshUnreadCountsMessage));
|
||||
break;
|
||||
case nameof(AccountSynchronizerStateChanged):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.AccountSynchronizerStateChanged));
|
||||
break;
|
||||
case nameof(AccountSynchronizationProgressUpdatedMessage):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.AccountSynchronizationProgressUpdatedMessage));
|
||||
break;
|
||||
case nameof(AccountFolderConfigurationUpdated):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.AccountFolderConfigurationUpdated));
|
||||
break;
|
||||
case nameof(CopyAuthURLRequested):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.CopyAuthURLRequested));
|
||||
break;
|
||||
case nameof(NewMailSynchronizationRequested):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.NewMailSynchronizationRequested));
|
||||
break;
|
||||
case nameof(AccountCacheResetMessage):
|
||||
WeakReferenceMessenger.Default.Send(JsonSerializer.Deserialize(messageJson, CommunicationMessagesContext.Default.AccountCacheResetMessage));
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Invalid data type name passed to client.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ServerDisconnected(AppServiceConnection sender, AppServiceClosedEventArgs args)
|
||||
{
|
||||
Log.Information("Server disconnected.");
|
||||
}
|
||||
|
||||
public async Task QueueRequestAsync(IRequestBase request, Guid accountId)
|
||||
{
|
||||
var queuePackage = new ServerRequestPackage(accountId, request);
|
||||
|
||||
var queueResponse = await GetResponseInternalAsync<bool, ServerRequestPackage>(queuePackage, new Dictionary<string, object>()
|
||||
{
|
||||
{ MessageConstants.MessageDataRequestAccountIdKey, accountId }
|
||||
});
|
||||
|
||||
queueResponse.ThrowIfFailed();
|
||||
}
|
||||
|
||||
public Task<WinoServerResponse<TResponse>> GetResponseAsync<TResponse, TRequestType>(TRequestType message, CancellationToken cancellationToken = default) where TRequestType : IClientMessage
|
||||
=> GetResponseInternalAsync<TResponse, TRequestType>(message, cancellationToken: cancellationToken);
|
||||
|
||||
[RequiresDynamicCode("Calls System.Text.Json.JsonSerializer.Serialize<TValue>(TValue, JsonSerializerOptions)")]
|
||||
[RequiresUnreferencedCode("Calls System.Text.Json.JsonSerializer.Serialize<TValue>(TValue, JsonSerializerOptions)")]
|
||||
private async Task<WinoServerResponse<TResponse>> GetResponseInternalAsync<TResponse, TRequestType>(TRequestType message,
|
||||
Dictionary<string, object> parameters = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (Status != WinoServerConnectionStatus.Connected)
|
||||
await ConnectAsync();
|
||||
|
||||
if (Connection == null) return WinoServerResponse<TResponse>.CreateErrorResponse("Server connection is not established.");
|
||||
|
||||
string serializedMessage = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
serializedMessage = JsonSerializer.Serialize(message, _jsonSerializerOptions);
|
||||
}
|
||||
catch (Exception serializationException)
|
||||
{
|
||||
Logger.Error(serializationException, $"Failed to serialize client message for sending.");
|
||||
return WinoServerResponse<TResponse>.CreateErrorResponse($"Failed to serialize message.\n{serializationException.Message}");
|
||||
}
|
||||
|
||||
AppServiceResponse response = null;
|
||||
|
||||
try
|
||||
{
|
||||
var valueSet = new ValueSet
|
||||
{
|
||||
{ MessageConstants.MessageTypeKey, (int)MessageType.ServerMessage },
|
||||
{ MessageConstants.MessageDataKey, serializedMessage },
|
||||
{ MessageConstants.MessageDataTypeKey, message.GetType().Name }
|
||||
};
|
||||
|
||||
// Add additional parameters into ValueSet
|
||||
if (parameters != null)
|
||||
{
|
||||
foreach (var item in parameters)
|
||||
{
|
||||
valueSet.Add(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
response = await Connection.SendMessageAsync(valueSet).AsTask(cancellationToken);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
return WinoServerResponse<TResponse>.CreateErrorResponse($"Request is canceled by client.");
|
||||
}
|
||||
catch (Exception serverSendException)
|
||||
{
|
||||
Logger.Error(serverSendException, $"Failed to send message to server.");
|
||||
return WinoServerResponse<TResponse>.CreateErrorResponse($"Failed to send message to server.\n{serverSendException.Message}");
|
||||
}
|
||||
|
||||
// It should be always Success.
|
||||
if (response.Status != AppServiceResponseStatus.Success)
|
||||
return WinoServerResponse<TResponse>.CreateErrorResponse($"Wino Server responded with '{response.Status}' status to message delivery.");
|
||||
|
||||
// All responses must contain a message data.
|
||||
if (!(response.Message.TryGetValue(MessageConstants.MessageDataKey, out object messageDataObject) && messageDataObject is string messageJson))
|
||||
return WinoServerResponse<TResponse>.CreateErrorResponse("Server response did not contain message data.");
|
||||
|
||||
// Try deserialize the message data.
|
||||
try
|
||||
{
|
||||
return JsonSerializer.Deserialize<WinoServerResponse<TResponse>>(messageJson);
|
||||
}
|
||||
catch (Exception jsonDeserializationError)
|
||||
{
|
||||
Logger.Error(jsonDeserializationError, $"Failed to deserialize server response message data.");
|
||||
return WinoServerResponse<TResponse>.CreateErrorResponse($"Failed to deserialize Wino server response message data.\n{jsonDeserializationError.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(WinoServerConnectionEstablished message)
|
||||
=> ConnectingHandle?.TrySetResult(true);
|
||||
}
|
||||
@@ -32,7 +32,6 @@ public abstract class WinoApplication : Application, IRecipient<LanguageChanged>
|
||||
public IServiceProvider Services { get; }
|
||||
protected IWinoLogger LogInitializer { get; }
|
||||
protected IApplicationConfiguration AppConfiguration { get; }
|
||||
protected IWinoServerConnectionManager<AppServiceConnection> AppServiceConnectionManager { get; }
|
||||
public INewThemeService NewThemeService { get; }
|
||||
public IUnderlyingThemeService UnderlyingThemeService { get; }
|
||||
public IThumbnailService ThumbnailService { get; }
|
||||
@@ -54,7 +53,6 @@ public abstract class WinoApplication : Application, IRecipient<LanguageChanged>
|
||||
LogInitializer = Services.GetService<IWinoLogger>();
|
||||
AppConfiguration = Services.GetService<IApplicationConfiguration>();
|
||||
|
||||
AppServiceConnectionManager = Services.GetService<IWinoServerConnectionManager<AppServiceConnection>>();
|
||||
NewThemeService = Services.GetService<INewThemeService>();
|
||||
DatabaseService = Services.GetService<IDatabaseService>();
|
||||
TranslationService = Services.GetService<ITranslationService>();
|
||||
|
||||
Reference in New Issue
Block a user