using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using CommunityToolkit.Mvvm.Messaging; using gehGassi.Dto; using gehGassi.Dto.Messages; using gehGassiApp.Core.Interfaces; using gehGassiApp.Core.Interfaces.Synchronization; using gehGassiApp.Core.Messaging; using Microsoft.AspNetCore.SignalR.Client; namespace gehGassiApp.Core.Services { /// /// Service der Daten vom AppHub des Servers empfangen kann /// public class AppHubService : IAppHubService { private string _baseAddress; private HubConnection _connection; /// /// Erstellt eine Instanz /// /// Basis-Adresse des Servers public AppHubService(string baseAddress) { _baseAddress = baseAddress; if (_baseAddress.EndsWith("/")) _baseAddress = _baseAddress.Substring(0, _baseAddress.Length - 1); } /// /// Connection zum Hub erstellen /// private void CreateConnection(string accessToken) { _connection = new HubConnectionBuilder().WithUrl($"{_baseAddress}/appHub", o => { o.AccessTokenProvider = () => Task.FromResult(accessToken); o.HttpMessageHandlerFactory = (message) => { #if DEBUG // bypass SSL certificate if (message is HttpClientHandler clientHandler) { clientHandler.ServerCertificateCustomValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; } #endif return message; }; }).WithAutomaticReconnect().Build(); } /// /// Setzen der Basis-Adresse des Servers /// /// Basis-Adresse public async Task SetBaseAddressAsync(string baseAddress) { _baseAddress = baseAddress; if (_baseAddress.EndsWith("/")) _baseAddress = _baseAddress.Substring(0, _baseAddress.Length - 1); await DisconnectAsync(); } public async Task ConnectAsync(string accessToken) { if (_connection != null && _connection.State == HubConnectionState.Connected) return; if (_connection != null && _connection.State == HubConnectionState.Connecting) return; if (_connection != null && _connection.State == HubConnectionState.Reconnecting) return; //Buchen der Nachrichten CreateConnection(accessToken); _connection.On("AppUserChanged", async () => await AppUserChangedAsync()); _connection.On("NewsCategoriesChanged", async () => await NewsCategoriesChangedAsync()); _connection.On("ConversationMessageAdded", async (MessageDto messageDto) => await ConversationMessageAddedAsync(messageDto)); _connection.On("MessageAdded", async () => await MessageAddedAsync()); _connection.On("SystemMessageAdded", async () => await SystemMessageAddedAsync()); _connection.On("Logout", async () => await LogoutAsync()); try { await _connection.StartAsync().ConfigureAwait(false); } catch (Exception ex) { Debug.WriteLine(ex); } } /// /// Verbindung trennen /// /// Task public async Task DisconnectAsync() { if (_connection != null) { try { await _connection.StopAsync(); await _connection.DisposeAsync(); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } } //CreateConnection(); } /// /// Gibt zurück ob eine SignalR Verbindung besteht /// /// true wenn ja oder reconnecting, false sonst public bool IsConnected() { if (_connection == null) return false; return _connection.State != HubConnectionState.Disconnected; } /// /// Buchen der Events eines App-Users /// /// Id des AppUsers /// Task public async Task JoinAppUserAsync(string appUserId) { if(_connection == null || string.IsNullOrWhiteSpace(appUserId)) return; if (_connection is { State: HubConnectionState.Connected }) { await _connection.SendAsync("JoinAppUser", appUserId); } } /// /// Abbestellen der Events eines App-Users /// /// Id des AppUsers /// Task public async Task LeaveAppUserAsync(string appUserId) { if (_connection == null || string.IsNullOrWhiteSpace(appUserId)) return; if (_connection is { State: HubConnectionState.Connected }) { await _connection.SendAsync("LeaveAppUser", appUserId); } } /// /// Buchen der Events einer Konversation /// /// Id der Konversation /// Id des AppUsers /// Task public async Task JoinConversationAsync(string conversationId, string appUserId) { if (_connection == null || string.IsNullOrWhiteSpace(appUserId) || string.IsNullOrWhiteSpace(conversationId)) return; if (_connection is { State: HubConnectionState.Connected }) { await _connection.SendAsync("JoinConversation", conversationId, appUserId); } } /// /// Abbestellen der Events einer Konversation /// /// Id der Konversation /// Id des AppUsers /// Task public async Task LeaveConversationAsync(string conversationId, string appUserId) { if (_connection == null || string.IsNullOrWhiteSpace(appUserId) || string.IsNullOrWhiteSpace(conversationId)) return; if (_connection is { State: HubConnectionState.Connected }) { await _connection.SendAsync("LeaveConversation", conversationId, appUserId); } } #region EventHandler /// /// Handler wenn sich der App-User geändert hat /// /// Task private async Task AppUserChangedAsync() { await Task.Delay(1); WeakReferenceMessenger.Default.Send(new SignalRAppUserChangedMessage()); } /// /// Handler wenn sich News-Kategorien geändert haben /// /// Task private async Task NewsCategoriesChangedAsync() { await Task.Delay(1); WeakReferenceMessenger.Default.Send(new SignalRNewsCategoriesChangedMessage()); } /// /// Handler wenn zu einer Konversation eine Nachricht hinzugefügt wurde /// /// /// private async Task ConversationMessageAddedAsync(MessageDto message) { await Task.Delay(1); WeakReferenceMessenger.Default.Send(new SignalRConversationMessageAddedMessage(message.ConversationId)); } /// /// Handler wenn neue Nachrichten für einen Benutzer da sind /// /// Task private async Task MessageAddedAsync() { await Task.Delay(1); WeakReferenceMessenger.Default.Send(new MessagesChangedMessage()); } /// /// Handler wenn neue SystemNachrichten für einen Benutzer da sind /// /// Task private async Task SystemMessageAddedAsync() { await Task.Delay(1); WeakReferenceMessenger.Default.Send(new SignalRSystemMessagesChangedMessage()); } /// /// Handler wenn der Benutzer abgemeldet werden soll /// /// Task private async Task LogoutAsync() { await Task.Delay(1); WeakReferenceMessenger.Default.Send(new LogoutMessage()); } #endregion } }