< Summary

Class:DCL.Social.Chat.PrivateChatWindowController
Assembly:PrivateChatWindowHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/PrivateChatWindow/PrivateChatWindowController.cs
Covered lines:155
Uncovered lines:30
Coverable lines:185
Total lines:422
Line coverage:83.7% (155 of 185)
Covered branches:0
Total branches:0
Covered methods:23
Total methods:32
Method coverage:71.8% (23 of 32)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
PrivateChatWindowController(...)0%110100%
Initialize(...)0%220100%
<Initialize()0%4.123050%
Setup(...)0%330100%
SetVisibility(...)0%770100%
Dispose()0%660100%
HandleSendChatMessage(...)0%6.686073.33%
MinimizeView()0%2100%
HandleMessageReceived(...)0%880100%
CheckOwnPlayerMentionInDMs(...)0%660100%
Hide()0%2.152066.67%
Show()0%2100%
HandlePressBack()0%220100%
Unfriend(...)0%2100%
IsMessageFomCurrentConversation(...)0%330100%
MarkUserChatMessagesAsRead()0%110100%
HandleInputFieldSelected()0%2100%
HandleViewFocused(...)0%6200%
SetVisiblePanelList(...)0%220100%
RequestPrivateMessages(...)0%220100%
RequestOldConversations()0%3.033085.71%
IsLoadingMessages()0%110100%
WaitForRequestTimeOutThenHideLoadingFeedback()0%550100%
HandleMessageBlockedBySpam(...)0%2100%
ResetPagination()0%110100%
Focus()0%110100%
SomeoneMentionedFromContextMenu(...)0%6200%
UnblockUser(...)0%20400%

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.Interface;
 6using DCL.Social.Chat.Mentions;
 7using DCL.Social.Friends;
 8using DCLServices.CopyPaste.Analytics;
 9using SocialFeaturesAnalytics;
 10using UnityEngine;
 11
 12namespace DCL.Social.Chat
 13{
 14    public class PrivateChatWindowController : IHUD
 15    {
 16        private const int USER_PRIVATE_MESSAGES_TO_REQUEST_FOR_INITIAL_LOAD = 30;
 17        private const float REQUEST_MESSAGES_TIME_OUT = 2;
 18        internal const int USER_PRIVATE_MESSAGES_TO_REQUEST_FOR_SHOW_MORE = 10;
 19
 41720        public IPrivateChatComponentView View { get; private set; }
 21
 22        private readonly DataStore dataStore;
 23        private readonly IUserProfileBridge userProfileBridge;
 24        private readonly IChatController chatController;
 25        private readonly IFriendsController friendsController;
 26        private readonly ISocialAnalytics socialAnalytics;
 27        private readonly IMouseCatcher mouseCatcher;
 28        private readonly IChatMentionSuggestionProvider chatMentionSuggestionProvider;
 29        private readonly IClipboard clipboard;
 30        private readonly ICopyPasteAnalyticsService copyPasteAnalyticsService;
 31        private ChatHUDController chatHudController;
 32        private UserProfile conversationProfile;
 33        private float lastRequestTime;
 2234        private CancellationTokenSource deactivateFadeOutCancellationToken = new CancellationTokenSource();
 35        private bool shouldRequestMessages;
 2236        private ulong oldestTimestamp = ulong.MaxValue;
 37        private string oldestMessageId;
 38        private string conversationUserId;
 3239        private BaseVariable<HashSet<string>> visibleTaskbarPanels => dataStore.HUDs.visibleTaskbarPanels;
 040        private UserProfile ownUserProfile => userProfileBridge.GetOwn();
 41
 42        public event Action OnBack;
 43        public event Action OnClosed;
 44
 2245        public PrivateChatWindowController(DataStore dataStore,
 46            IUserProfileBridge userProfileBridge,
 47            IChatController chatController,
 48            IFriendsController friendsController,
 49            ISocialAnalytics socialAnalytics,
 50            IMouseCatcher mouseCatcher,
 51            IChatMentionSuggestionProvider chatMentionSuggestionProvider,
 52            IClipboard clipboard,
 53            ICopyPasteAnalyticsService copyPasteAnalyticsService)
 54        {
 2255            this.dataStore = dataStore;
 2256            this.userProfileBridge = userProfileBridge;
 2257            this.chatController = chatController;
 2258            this.friendsController = friendsController;
 2259            this.socialAnalytics = socialAnalytics;
 2260            this.mouseCatcher = mouseCatcher;
 2261            this.chatMentionSuggestionProvider = chatMentionSuggestionProvider;
 2262            this.clipboard = clipboard;
 2263            this.copyPasteAnalyticsService = copyPasteAnalyticsService;
 2264        }
 65
 66        public void Initialize(IPrivateChatComponentView view)
 67        {
 2368            View = view;
 2369            View.Initialize(friendsController, socialAnalytics);
 2370            view.OnPressBack -= HandlePressBack;
 2371            view.OnPressBack += HandlePressBack;
 2372            view.OnClose -= Hide;
 2373            view.OnClose += Hide;
 2374            view.OnMinimize += MinimizeView;
 2375            view.OnUnfriend += Unfriend;
 76
 2377            if (mouseCatcher != null)
 2278                mouseCatcher.OnMouseLock += Hide;
 79
 2380            view.OnRequireMoreMessages += RequestOldConversations;
 2381            view.ChatHUD.OnUnblockUser += UnblockUser;
 82
 2383            dataStore.mentions.someoneMentionedFromContextMenu.OnChange += SomeoneMentionedFromContextMenu;
 84
 2385            chatHudController = new ChatHUDController(dataStore, userProfileBridge, false,
 86                async (name, count, ct) =>
 87                {
 388                    return await chatMentionSuggestionProvider.GetProfilesStartingWith(name, count, new[]
 89                    {
 90                        userProfileBridge.GetOwn(),
 91                        userProfileBridge.Get(conversationUserId)
 92                    }, ct);
 393                },
 94                socialAnalytics,
 95                chatController,
 96                clipboard,
 97                copyPasteAnalyticsService);
 98
 2399            chatHudController.Initialize(view.ChatHUD);
 23100            chatHudController.SortingStrategy = new ChatEntrySortingByTimestamp();
 23101            chatHudController.OnInputFieldSelected += HandleInputFieldSelected;
 23102            chatHudController.OnSendMessage += HandleSendChatMessage;
 23103            chatHudController.OnMessageSentBlockedBySpam += HandleMessageBlockedBySpam;
 104
 23105            chatController.OnAddMessage -= HandleMessageReceived;
 23106            chatController.OnAddMessage += HandleMessageReceived;
 23107        }
 108
 109        public void Setup(string newConversationUserId)
 110        {
 20111            if (string.IsNullOrEmpty(newConversationUserId) || newConversationUserId == conversationUserId)
 1112                return;
 113
 19114            var newConversationUserProfile = userProfileBridge.Get(newConversationUserId);
 115
 19116            conversationUserId = newConversationUserId;
 19117            conversationProfile = newConversationUserProfile;
 19118            chatHudController.ClearAllEntries();
 19119            View.ChatHUD.SetConversationUserId(newConversationUserId);
 19120            shouldRequestMessages = true;
 19121        }
 122
 123        public void SetVisibility(bool visible)
 124        {
 19125            if (View.IsActive == visible)
 3126                return;
 127
 16128            SetVisiblePanelList(visible);
 16129            chatHudController.SetVisibility(visible);
 16130            dataStore.HUDs.chatInputVisible.Set(visible);
 131
 16132            if (visible)
 133            {
 11134                View?.SetLoadingMessagesActive(false);
 11135                View?.SetOldMessagesLoadingActive(false);
 136
 11137                if (conversationProfile != null)
 138                {
 10139                    var userStatus = friendsController.GetUserStatus(conversationUserId);
 140
 10141                    View.Setup(conversationProfile,
 142                        userStatus.presence == PresenceStatus.ONLINE,
 143                        userProfileBridge.GetOwn().IsBlocked(conversationUserId));
 144
 10145                    if (shouldRequestMessages)
 146                    {
 9147                        ResetPagination();
 148
 9149                        RequestPrivateMessages(
 150                            conversationUserId,
 151                            USER_PRIVATE_MESSAGES_TO_REQUEST_FOR_INITIAL_LOAD,
 152                            null);
 153
 9154                        shouldRequestMessages = false;
 155                    }
 156                }
 157
 11158                View.Show();
 11159                Focus();
 160            }
 161            else
 162            {
 5163                chatHudController.UnfocusInputField();
 5164                View.Hide();
 165            }
 5166        }
 167
 168        public void Dispose()
 169        {
 22170            if (chatHudController != null)
 171            {
 22172                chatHudController.OnInputFieldSelected -= HandleInputFieldSelected;
 22173                chatHudController.OnSendMessage -= HandleSendChatMessage;
 22174                chatHudController.OnMessageSentBlockedBySpam -= HandleMessageBlockedBySpam;
 22175                chatHudController.Dispose();
 176            }
 177
 22178            if (chatController != null)
 22179                chatController.OnAddMessage -= HandleMessageReceived;
 180
 22181            if (mouseCatcher != null)
 21182                mouseCatcher.OnMouseLock -= Hide;
 183
 22184            if (View != null)
 185            {
 22186                View.OnPressBack -= HandlePressBack;
 22187                View.OnClose -= Hide;
 22188                View.OnMinimize -= MinimizeView;
 22189                View.OnUnfriend -= Unfriend;
 22190                View.OnFocused -= HandleViewFocused;
 22191                View.OnRequireMoreMessages -= RequestOldConversations;
 192
 44193                if (View.ChatHUD != null) View.ChatHUD.OnUnblockUser -= UnblockUser;
 194
 22195                View.Dispose();
 196            }
 197
 22198            dataStore.mentions.someoneMentionedFromContextMenu.OnChange -= SomeoneMentionedFromContextMenu;
 22199        }
 200
 201        private void HandleSendChatMessage(ChatMessage message)
 202        {
 1203            if (string.IsNullOrEmpty(conversationProfile.userName))
 0204                return;
 205
 1206            message.messageType = ChatMessage.Type.PRIVATE;
 1207            message.recipient = conversationProfile.userName;
 1208            message.receiverId = conversationProfile.userId;
 209
 1210            bool isValidMessage = !string.IsNullOrEmpty(message.body)
 211                                  && !string.IsNullOrWhiteSpace(message.body)
 212                                  && !string.IsNullOrEmpty(message.recipient);
 213
 1214            if (isValidMessage)
 215            {
 1216                chatHudController.ResetInputField();
 1217                chatHudController.FocusInputField();
 218            }
 219            else
 220            {
 0221                SetVisibility(false);
 0222                OnClosed?.Invoke();
 0223                return;
 224            }
 225
 226            // If Kernel allowed for private messages without the whisper param we could avoid this line
 1227            message.body = $"/w {message.recipient} {message.body}";
 228
 1229            chatController.Send(message);
 1230        }
 231
 232        private void MinimizeView() =>
 0233            SetVisibility(false);
 234
 235        private void HandleMessageReceived(ChatMessage[] messages)
 236        {
 6237            var messageLogUpdated = false;
 238
 6239            var ownPlayerAlreadyMentioned = false;
 240
 26241            foreach (var message in messages)
 242            {
 7243                if (!ownPlayerAlreadyMentioned)
 7244                    ownPlayerAlreadyMentioned = CheckOwnPlayerMentionInDMs(message);
 245
 7246                if (!IsMessageFomCurrentConversation(message)) continue;
 247
 7248                chatHudController.SetChatMessage(message, limitMaxEntries: false);
 249
 7250                if (message.timestamp < oldestTimestamp)
 251                {
 4252                    oldestTimestamp = message.timestamp;
 4253                    oldestMessageId = message.messageId;
 254                }
 255
 7256                View?.SetLoadingMessagesActive(false);
 7257                View?.SetOldMessagesLoadingActive(false);
 258
 7259                messageLogUpdated = true;
 260            }
 261
 6262            deactivateFadeOutCancellationToken.Cancel();
 6263            deactivateFadeOutCancellationToken = new CancellationTokenSource();
 264
 6265            if (View.IsActive && messageLogUpdated)
 1266                MarkUserChatMessagesAsRead();
 6267        }
 268
 269        private bool CheckOwnPlayerMentionInDMs(ChatMessage message)
 270        {
 7271            var ownUserProfile = userProfileBridge.GetOwn();
 272
 7273            if (message.sender == ownUserProfile.userId ||
 274                (message.sender == conversationUserId && View.IsActive) ||
 275                message.messageType != ChatMessage.Type.PRIVATE ||
 276                !MentionsUtils.IsUserMentionedInText(ownUserProfile.userName, message.body))
 6277                return false;
 278
 1279            dataStore.mentions.ownPlayerMentionedInDM.Set(message.sender, true);
 1280            return true;
 281        }
 282
 283        private void Hide()
 284        {
 2285            SetVisibility(false);
 2286            OnClosed?.Invoke();
 0287        }
 288
 289        private void Show()
 290        {
 0291            SetVisibility(true);
 0292        }
 293
 294        private void HandlePressBack() =>
 1295            OnBack?.Invoke();
 296
 297        private void Unfriend(string friendId)
 298        {
 0299            Hide();
 0300        }
 301
 302        private bool IsMessageFomCurrentConversation(ChatMessage message)
 303        {
 7304            return message.messageType == ChatMessage.Type.PRIVATE &&
 305                   (message.sender == conversationUserId || message.recipient == conversationUserId);
 306        }
 307
 308        private void MarkUserChatMessagesAsRead() =>
 12309            chatController.MarkMessagesAsSeen(conversationUserId);
 310
 311        private void HandleInputFieldSelected()
 312        {
 0313            Show();
 314
 315            // The messages from 'conversationUserId' are marked as read if the player clicks on the input field of the 
 316            //MarkUserChatMessagesAsRead();
 0317        }
 318
 319        private void HandleViewFocused(bool focused)
 320        {
 0321            if (focused)
 322            {
 0323                deactivateFadeOutCancellationToken.Cancel();
 0324                deactivateFadeOutCancellationToken = new CancellationTokenSource();
 325            }
 0326        }
 327
 328        private void SetVisiblePanelList(bool visible)
 329        {
 16330            HashSet<string> newSet = visibleTaskbarPanels.Get();
 331
 16332            if (visible)
 11333                newSet.Add("PrivateChatChannel");
 334            else
 5335                newSet.Remove("PrivateChatChannel");
 336
 16337            visibleTaskbarPanels.Set(newSet, true);
 16338        }
 339
 340        internal void RequestPrivateMessages(string userId, int limit, string fromMessageId)
 341        {
 10342            View?.SetLoadingMessagesActive(true);
 10343            chatController.GetPrivateMessages(userId, limit, fromMessageId);
 10344            WaitForRequestTimeOutThenHideLoadingFeedback().Forget();
 10345        }
 346
 347        internal void RequestOldConversations()
 348        {
 1349            if (IsLoadingMessages()) return;
 350
 1351            chatController.GetPrivateMessages(
 352                conversationUserId,
 353                USER_PRIVATE_MESSAGES_TO_REQUEST_FOR_SHOW_MORE,
 354                oldestMessageId);
 355
 1356            lastRequestTime = Time.realtimeSinceStartup;
 1357            View?.SetOldMessagesLoadingActive(true);
 1358            WaitForRequestTimeOutThenHideLoadingFeedback().Forget();
 1359        }
 360
 361        private bool IsLoadingMessages() =>
 1362            Time.realtimeSinceStartup - lastRequestTime < REQUEST_MESSAGES_TIME_OUT;
 363
 364        private async UniTaskVoid WaitForRequestTimeOutThenHideLoadingFeedback()
 365        {
 11366            lastRequestTime = Time.realtimeSinceStartup;
 367
 273368            await UniTask.WaitUntil(() => Time.realtimeSinceStartup - lastRequestTime > REQUEST_MESSAGES_TIME_OUT);
 369
 11370            View?.SetLoadingMessagesActive(false);
 11371            View?.SetOldMessagesLoadingActive(false);
 11372        }
 373
 374        private void HandleMessageBlockedBySpam(ChatMessage message)
 375        {
 0376            chatHudController.SetChatMessage(new ChatEntryModel
 377                              {
 378                                  timestamp = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
 379                                  bodyText = "You sent too many messages in a short period of time. Please wait and try 
 380                                  messageId = Guid.NewGuid().ToString(),
 381                                  messageType = ChatMessage.Type.SYSTEM,
 382                                  subType = ChatEntryModel.SubType.RECEIVED
 383                              })
 384                             .Forget();
 0385        }
 386
 387        private void ResetPagination()
 388        {
 9389            oldestTimestamp = long.MaxValue;
 9390            oldestMessageId = null;
 9391        }
 392
 393        private void Focus()
 394        {
 11395            chatHudController.FocusInputField();
 11396            MarkUserChatMessagesAsRead();
 11397        }
 398
 399        private void SomeoneMentionedFromContextMenu(string mention, string _)
 400        {
 0401            if (!View.IsActive)
 0402                return;
 403
 0404            View.ChatHUD.AddTextIntoInputField(mention);
 0405        }
 406
 407        private void UnblockUser(string userId)
 408        {
 0409            if (!ownUserProfile.IsBlocked(userId)) return;
 410
 0411            dataStore.notifications.GenericConfirmation.Set(GenericConfirmationNotificationData.CreateUnBlockUserData(
 412                userProfileBridge.Get(userId)?.userName,
 413                () =>
 414                {
 0415                    ownUserProfile.Unblock(userId);
 0416                    WebInterface.SendUnblockPlayer(userId);
 0417                    socialAnalytics.SendPlayerUnblocked(friendsController.IsFriend(userId), PlayerActionSource.MyProfile
 418
 0419                }), true);
 0420        }
 421    }
 422}