< Summary

Class:PrivateChatWindowController
Assembly:PrivateChatWindowHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/PrivateChatWindow/PrivateChatWindowController.cs
Covered lines:136
Uncovered lines:28
Coverable lines:164
Total lines:363
Line coverage:82.9% (136 of 164)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
PrivateChatWindowController(...)0%110100%
Initialize(...)0%330100%
Setup(...)0%330100%
SetVisibility(...)0%770100%
Dispose()0%550100%
HandleSendChatMessage(...)0%6.846071.43%
MinimizeView()0%2100%
HandleMessageReceived(...)0%770100%
Hide()0%2.152066.67%
Show()0%2100%
HandlePressBack()0%220100%
Unfriend(...)0%12300%
IsMessageFomCurrentConversation(...)0%330100%
MarkUserChatMessagesAsRead()0%110100%
HandleInputFieldSelected()0%2100%
HandleViewFocused(...)0%6200%
SetVisiblePanelList(...)0%220100%
HandleChatInputTriggered(...)0%12300%
RequestPrivateMessages(...)0%220100%
RequestOldConversations()0%3.033085.71%
IsLoadingMessages()0%110100%
WaitForRequestTimeOutThenHideLoadingFeedback()0%550100%
HandleMessageBlockedBySpam(...)0%2100%
ResetPagination()0%110100%
Focus()0%110100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/PrivateChatWindow/PrivateChatWindowController.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Threading;
 4using Cysharp.Threading.Tasks;
 5using DCL;
 6using DCL.Interface;
 7using DCl.Social.Friends;
 8using DCL.Social.Friends;
 9using SocialFeaturesAnalytics;
 10using UnityEngine;
 11
 12public class PrivateChatWindowController : IHUD
 13{
 14    private const int USER_PRIVATE_MESSAGES_TO_REQUEST_FOR_INITIAL_LOAD = 30;
 15    private const float REQUEST_MESSAGES_TIME_OUT = 2;
 16    internal const int USER_PRIVATE_MESSAGES_TO_REQUEST_FOR_SHOW_MORE = 10;
 17
 29218    public IPrivateChatComponentView View { get; private set; }
 19
 20    private readonly DataStore dataStore;
 21    private readonly IUserProfileBridge userProfileBridge;
 22    private readonly IChatController chatController;
 23    private readonly IFriendsController friendsController;
 24    private readonly ISocialAnalytics socialAnalytics;
 25    private readonly IMouseCatcher mouseCatcher;
 26    private readonly InputAction_Trigger toggleChatTrigger;
 27    private ChatHUDController chatHudController;
 28    private UserProfile conversationProfile;
 29    private bool skipChatInputTrigger;
 30    private float lastRequestTime;
 1731    private CancellationTokenSource deactivateFadeOutCancellationToken = new CancellationTokenSource();
 32    private bool shouldRequestMessages;
 1733    private ulong oldestTimestamp = ulong.MaxValue;
 34    private string oldestMessageId;
 35    private string conversationUserId;
 3236    private BaseVariable<HashSet<string>> visibleTaskbarPanels => dataStore.HUDs.visibleTaskbarPanels;
 37
 38    public event Action OnBack;
 39    public event Action OnClosed;
 40
 1741    public PrivateChatWindowController(DataStore dataStore,
 42        IUserProfileBridge userProfileBridge,
 43        IChatController chatController,
 44        IFriendsController friendsController,
 45        ISocialAnalytics socialAnalytics,
 46        IMouseCatcher mouseCatcher,
 47        InputAction_Trigger toggleChatTrigger)
 48    {
 1749        this.dataStore = dataStore;
 1750        this.userProfileBridge = userProfileBridge;
 1751        this.chatController = chatController;
 1752        this.friendsController = friendsController;
 1753        this.socialAnalytics = socialAnalytics;
 1754        this.mouseCatcher = mouseCatcher;
 1755        this.toggleChatTrigger = toggleChatTrigger;
 1756    }
 57
 58    public void Initialize(IPrivateChatComponentView view = null)
 59    {
 1860        view ??= PrivateChatWindowComponentView.Create();
 1861        View = view;
 1862        View.Initialize(friendsController, socialAnalytics);
 1863        view.OnPressBack -= HandlePressBack;
 1864        view.OnPressBack += HandlePressBack;
 1865        view.OnClose -= Hide;
 1866        view.OnClose += Hide;
 1867        view.OnMinimize += MinimizeView;
 1868        view.OnUnfriend += Unfriend;
 69
 1870        if (mouseCatcher != null)
 1771            mouseCatcher.OnMouseLock += Hide;
 72
 1873        view.OnRequireMoreMessages += RequestOldConversations;
 74
 1875        chatHudController = new ChatHUDController(dataStore, userProfileBridge, false);
 1876        chatHudController.Initialize(view.ChatHUD);
 1877        chatHudController.OnInputFieldSelected += HandleInputFieldSelected;
 1878        chatHudController.OnSendMessage += HandleSendChatMessage;
 1879        chatHudController.OnMessageSentBlockedBySpam += HandleMessageBlockedBySpam;
 80
 1881        chatController.OnAddMessage -= HandleMessageReceived;
 1882        chatController.OnAddMessage += HandleMessageReceived;
 83
 1884        toggleChatTrigger.OnTriggered += HandleChatInputTriggered;
 1885    }
 86
 87    public void Setup(string newConversationUserId)
 88    {
 1589        if (string.IsNullOrEmpty(newConversationUserId) || newConversationUserId == conversationUserId)
 190            return;
 91
 1492        var newConversationUserProfile = userProfileBridge.Get(newConversationUserId);
 93
 1494        conversationUserId = newConversationUserId;
 1495        conversationProfile = newConversationUserProfile;
 1496        chatHudController.ClearAllEntries();
 1497        shouldRequestMessages = true;
 1498    }
 99
 100    public void SetVisibility(bool visible)
 101    {
 19102        if (View.IsActive == visible)
 3103            return;
 104
 16105        SetVisiblePanelList(visible);
 106
 16107        if (visible)
 108        {
 11109            View?.SetLoadingMessagesActive(false);
 11110            View?.SetOldMessagesLoadingActive(false);
 111
 11112            if (conversationProfile != null)
 113            {
 10114                var userStatus = friendsController.GetUserStatus(conversationUserId);
 10115                View.Setup(conversationProfile,
 116                    userStatus.presence == PresenceStatus.ONLINE,
 117                    userProfileBridge.GetOwn().IsBlocked(conversationUserId));
 118
 10119                if (shouldRequestMessages)
 120                {
 9121                    ResetPagination();
 9122                    RequestPrivateMessages(
 123                        conversationUserId,
 124                        USER_PRIVATE_MESSAGES_TO_REQUEST_FOR_INITIAL_LOAD,
 125                        null);
 126
 9127                    shouldRequestMessages = false;
 128                }
 129            }
 130
 11131            View.Show();
 11132            Focus();
 133        }
 134        else
 135        {
 5136            chatHudController.UnfocusInputField();
 5137            View.Hide();
 138        }
 5139    }
 140
 141    public void Dispose()
 142    {
 17143        if (chatHudController != null)
 144        {
 17145            chatHudController.OnInputFieldSelected -= HandleInputFieldSelected;
 17146            chatHudController.OnSendMessage -= HandleSendChatMessage;
 17147            chatHudController.OnMessageSentBlockedBySpam -= HandleMessageBlockedBySpam;
 148        }
 149
 17150        if (chatController != null)
 17151            chatController.OnAddMessage -= HandleMessageReceived;
 152
 17153        if (mouseCatcher != null)
 16154            mouseCatcher.OnMouseLock -= Hide;
 155
 17156        toggleChatTrigger.OnTriggered -= HandleChatInputTriggered;
 157
 17158        if (View != null)
 159        {
 17160            View.OnPressBack -= HandlePressBack;
 17161            View.OnClose -= Hide;
 17162            View.OnMinimize -= MinimizeView;
 17163            View.OnUnfriend -= Unfriend;
 17164            View.OnFocused -= HandleViewFocused;
 17165            View.OnRequireMoreMessages -= RequestOldConversations;
 17166            View.Dispose();
 167        }
 17168    }
 169
 170    private void HandleSendChatMessage(ChatMessage message)
 171    {
 1172        if (string.IsNullOrEmpty(conversationProfile.userName))
 0173            return;
 174
 1175        message.messageType = ChatMessage.Type.PRIVATE;
 1176        message.recipient = conversationProfile.userName;
 177
 1178        bool isValidMessage = !string.IsNullOrEmpty(message.body)
 179                              && !string.IsNullOrWhiteSpace(message.body)
 180                              && !string.IsNullOrEmpty(message.recipient);
 181
 1182        if (isValidMessage)
 183        {
 1184            chatHudController.ResetInputField();
 1185            chatHudController.FocusInputField();
 186        }
 187        else
 188        {
 0189            SetVisibility(false);
 0190            OnClosed?.Invoke();
 0191            return;
 192        }
 193
 194        // If Kernel allowed for private messages without the whisper param we could avoid this line
 1195        message.body = $"/w {message.recipient} {message.body}";
 196
 1197        chatController.Send(message);
 1198    }
 199
 0200    private void MinimizeView() => SetVisibility(false);
 201
 202    private void HandleMessageReceived(ChatMessage[] messages)
 203    {
 4204        var messageLogUpdated = false;
 205
 18206        foreach (var message in messages)
 207        {
 5208            if (!IsMessageFomCurrentConversation(message)) continue;
 209
 5210            chatHudController.AddChatMessage(message, limitMaxEntries: false);
 211
 5212            if (message.timestamp < oldestTimestamp)
 213            {
 2214                oldestTimestamp = message.timestamp;
 2215                oldestMessageId = message.messageId;
 216            }
 217
 5218            View?.SetLoadingMessagesActive(false);
 5219            View?.SetOldMessagesLoadingActive(false);
 220
 5221            messageLogUpdated = true;
 222        }
 223
 4224        deactivateFadeOutCancellationToken.Cancel();
 4225        deactivateFadeOutCancellationToken = new CancellationTokenSource();
 226
 4227        if (View.IsActive && messageLogUpdated)
 1228            MarkUserChatMessagesAsRead();
 4229    }
 230
 231    private void Hide()
 232    {
 2233        SetVisibility(false);
 2234        OnClosed?.Invoke();
 0235    }
 236
 237    private void Show()
 238    {
 0239        SetVisibility(true);
 0240    }
 241
 1242    private void HandlePressBack() => OnBack?.Invoke();
 243
 244    private void Unfriend(string friendId)
 245    {
 0246        dataStore.notifications.GenericConfirmation.Set(GenericConfirmationNotificationData.CreateUnFriendData(
 247            UserProfileController.userProfilesCatalog.Get(friendId)?.userName,
 248            () =>
 249            {
 0250                friendsController.RemoveFriend(friendId);
 0251                Hide();
 0252            }), true);
 0253    }
 254
 255    private bool IsMessageFomCurrentConversation(ChatMessage message)
 256    {
 5257        return message.messageType == ChatMessage.Type.PRIVATE &&
 258               (message.sender == conversationUserId || message.recipient == conversationUserId);
 259    }
 260
 261    private void MarkUserChatMessagesAsRead() =>
 12262        chatController.MarkMessagesAsSeen(conversationUserId);
 263
 264    private void HandleInputFieldSelected()
 265    {
 0266        Show();
 267        // The messages from 'conversationUserId' are marked as read if the player clicks on the input field of the priv
 268        //MarkUserChatMessagesAsRead();
 0269    }
 270
 271    private void HandleViewFocused(bool focused)
 272    {
 0273        if (focused)
 274        {
 0275            deactivateFadeOutCancellationToken.Cancel();
 0276            deactivateFadeOutCancellationToken = new CancellationTokenSource();
 277        }
 0278    }
 279
 280    private void SetVisiblePanelList(bool visible)
 281    {
 16282        HashSet<string> newSet = visibleTaskbarPanels.Get();
 16283        if (visible)
 11284            newSet.Add("PrivateChatChannel");
 285        else
 5286            newSet.Remove("PrivateChatChannel");
 287
 16288        visibleTaskbarPanels.Set(newSet, true);
 16289    }
 290
 291    private void HandleChatInputTriggered(DCLAction_Trigger action)
 292    {
 293        // race condition patch caused by unfocusing input field from invalid message on SendChatMessage
 294        // chat input trigger is the same key as sending the chat message from the input field
 0295        if (skipChatInputTrigger)
 296        {
 0297            skipChatInputTrigger = false;
 0298            return;
 299        }
 300
 0301        if (!View.IsActive)
 0302            return;
 0303        chatHudController.FocusInputField();
 0304    }
 305
 306    internal void RequestPrivateMessages(string userId, int limit, string fromMessageId)
 307    {
 10308        View?.SetLoadingMessagesActive(true);
 10309        chatController.GetPrivateMessages(userId, limit, fromMessageId);
 10310        WaitForRequestTimeOutThenHideLoadingFeedback().Forget();
 10311    }
 312
 313    internal void RequestOldConversations()
 314    {
 1315        if (IsLoadingMessages()) return;
 316
 1317        chatController.GetPrivateMessages(
 318            conversationUserId,
 319            USER_PRIVATE_MESSAGES_TO_REQUEST_FOR_SHOW_MORE,
 320            oldestMessageId);
 321
 1322        lastRequestTime = Time.realtimeSinceStartup;
 1323        View?.SetOldMessagesLoadingActive(true);
 1324        WaitForRequestTimeOutThenHideLoadingFeedback().Forget();
 1325    }
 326
 327    private bool IsLoadingMessages() =>
 1328        Time.realtimeSinceStartup - lastRequestTime < REQUEST_MESSAGES_TIME_OUT;
 329
 330    private async UniTaskVoid WaitForRequestTimeOutThenHideLoadingFeedback()
 331    {
 11332        lastRequestTime = Time.realtimeSinceStartup;
 333
 1245334        await UniTask.WaitUntil(() => Time.realtimeSinceStartup - lastRequestTime > REQUEST_MESSAGES_TIME_OUT);
 335
 11336        View?.SetLoadingMessagesActive(false);
 11337        View?.SetOldMessagesLoadingActive(false);
 11338    }
 339
 340    private void HandleMessageBlockedBySpam(ChatMessage message)
 341    {
 0342        chatHudController.AddChatMessage(new ChatEntryModel
 343        {
 344            timestamp = (ulong) DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
 345            bodyText = "You sent too many messages in a short period of time. Please wait and try again later.",
 346            messageId = Guid.NewGuid().ToString(),
 347            messageType = ChatMessage.Type.SYSTEM,
 348            subType = ChatEntryModel.SubType.RECEIVED
 349        });
 0350    }
 351
 352    private void ResetPagination()
 353    {
 9354        oldestTimestamp = long.MaxValue;
 9355        oldestMessageId = null;
 9356    }
 357
 358    private void Focus()
 359    {
 11360        chatHudController.FocusInputField();
 11361        MarkUserChatMessagesAsRead();
 11362    }
 363}