insight/src/Web/Insight.Web/Components/Dialogs/ChatDialog.razor.cs

222 lines
No EOL
7 KiB
C#

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<ChatDialog> 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<IDisposable> _subscriptions = [];
protected override Task OnInitializedAsync()
{
_subscriptions.Add(Bus.SubscribeAsync<ChatUserConnected>(UserConnected, p => p.User.Uid != SessionHandler.State.Uid));
_subscriptions.Add(Bus.SubscribeAsync<ChatUserDisconnected>(UserDisconnected, p => p.User.Uid != SessionHandler.State.Uid));
_subscriptions.Add(Bus.SubscribeAsync<ChatRefresh>(RefreshAsync, null));
_subscriptions.Add(Bus.SubscribeAsync<ChatMessageReceived>(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<string>("ScrollToBottom", "chatContainer");
// mock
NewMessages = 0;
}
}
}
private async Task GetSessionAsync(ChatUser user)
{
if (_currentUser is null) return;
var members = new List<ChatUser>() { _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<string>("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<string>("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<string>("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<string>("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;
}
}
}