using Insight.Infrastructure.Services; using Insight.Web.Constants; using Insight.Web.Models; using Insight.Web.Services; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.SignalR.Client; using Microsoft.JSInterop; using MongoDB.Driver; using MudBlazor; using Vaitr.Bus; using static Insight.Web.Constants.Events.Chat; namespace Insight.Web.Components.Dialogs; public partial class ChatDialog : IDisposable { [Inject] private Bus Bus { get; init; } = default!; [Inject] private ChatService ChatService { get; init; } = default!; [Inject] private SessionPool SessionCache { get; init; } = default!; [Inject] private SessionHandler SessionHandler { get; init; } = default!; [Inject] private IdentityService IdentityService { get; init; } = default!; [Inject] private AuthenticationStateProvider AuthenticationStateProvider { get; init; } = default!; [Inject] private IMongoDatabase Database { get; init; } = default!; [Inject] private IJSRuntime JSRuntime { get; init; } = default!; [Inject] private ISnackbar Snackbar { get; init; } = default!; [Inject] private ILogger Logger { get; init; } = default!; private int _newMessages; public int NewMessages { get { return _newMessages; } set { if (value != _newMessages) { _newMessages = value; //Bus.Publish(Events.Sessions.Changed); // test, bugt hölle } } } private enum Content { Contacts, Chat } private Content _content = Content.Contacts; private ChatUser? _currentUser; private ChatSession? _currentSession; private string? _currentMessage; private bool _disposed; private readonly List _subscriptions = []; protected override Task OnInitializedAsync() { _subscriptions.Add(Bus.SubscribeAsync(UserConnected, p => p.User.Uid != SessionHandler.State.Uid)); _subscriptions.Add(Bus.SubscribeAsync(UserDisconnected, p => p.User.Uid != SessionHandler.State.Uid)); _subscriptions.Add(Bus.SubscribeAsync(RefreshAsync, null)); _subscriptions.Add(Bus.SubscribeAsync(MessageReceived, p => p.Message.SenderId != SessionHandler.State.Uid)); return Task.CompletedTask; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { } else { _currentUser = ChatService.Users.FirstOrDefault(p => p.Key.Uid == SessionHandler.State.Uid).Key; if (_content == Content.Chat) { await JSRuntime.InvokeAsync("ScrollToBottom", "chatContainer"); // mock NewMessages = 0; } } } private async Task GetSessionAsync(ChatUser user) { if (_currentUser is null) return; var members = new List() { _currentUser, user }; var session = await ChatService.AddOrGetSession(members); _currentSession = session; _content = Content.Chat; await InvokeAsync(StateHasChanged); } private async Task SendAsync() { if (_currentSession is null || _currentUser is null || string.IsNullOrWhiteSpace(_currentMessage)) return; await _currentSession.SendMessage(_currentUser, _currentMessage, default); _currentMessage = string.Empty; await InvokeAsync(StateHasChanged); //await JSRuntime.InvokeAsync("ScrollToBottom", "chatContainer"); } private async ValueTask UserConnected(ChatUserConnected model, CancellationToken cancellationToken) { try { Notification.Information(Snackbar, $"{model.User.Username} Online", options => { //options.Onclick = (x) => null; options.HideIcon = true; options.ShowCloseIcon = false; options.RequireInteraction = false; options.ShowTransitionDuration = 0; options.HideTransitionDuration = 1000; options.VisibleStateDuration = 10000; }); await JSRuntime.InvokeAsync("PlayAudio", "chat_user_online"); } catch (Exception ex) { Logger.LogError("{exception}", ex.Message); } } private async ValueTask UserDisconnected(ChatUserDisconnected model, CancellationToken cancellationToken) { try { Notification.Information(Snackbar, $"{model.User.Username} Offline", options => { //options.Onclick = (x) => null; options.HideIcon = true; options.ShowCloseIcon = false; options.RequireInteraction = false; options.ShowTransitionDuration = 0; options.HideTransitionDuration = 1000; options.VisibleStateDuration = 10000; }); await JSRuntime.InvokeAsync("PlayAudio", "chat_user_online"); } catch (Exception ex) { Logger.LogError("{exception}", ex.Message); } } private async ValueTask RefreshAsync(ChatRefresh model, CancellationToken cancellationToken) { await InvokeAsync(StateHasChanged); } private async ValueTask MessageReceived(ChatMessageReceived model, CancellationToken cancellationToken) { try { Notification.Information(Snackbar, $"New message from: {model.Session.Members.FirstOrDefault(p => p.Uid == model.Message.SenderId)?.Username}", options => { options.Onclick = (x) => OpenSpecificChatWindow(model.Session); options.HideIcon = true; options.ShowCloseIcon = true; options.RequireInteraction = true; options.ShowTransitionDuration = 0; options.HideTransitionDuration = 0; options.VisibleStateDuration = 10000; options.DuplicatesBehavior = SnackbarDuplicatesBehavior.Prevent; }); // mock NewMessages++; if (_content != Content.Chat) { await JSRuntime.InvokeAsync("PlayAudio", "chat_message"); } await InvokeAsync(StateHasChanged); } catch (Exception ex) { Logger.LogError("{exception}", ex.ToString()); } } private async Task OpenSpecificChatWindow(ChatSession session) { _currentSession = session; _content = Content.Chat; _visible = true; await InvokeAsync(StateHasChanged); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (_disposed is false) return; if (disposing is false) return; try { } finally { _disposed = true; } } }