< Summary

Class:DCL.Chat.Notifications.ChatNotificationController
Assembly:NotificationMessagesHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/NotificationMessagesHUD/ChatNotificationController.cs
Covered lines:125
Uncovered lines:14
Coverable lines:139
Total lines:300
Line coverage:89.9% (125 of 139)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ChatNotificationController(...)0%110100%
SetVisibility(...)0%5.024060%
Dispose()0%110100%
VisiblePanelsChanged(...)0%2100%
HandleMessageAdded(...)0%13.5812077.78%
AddNotification()0%29.9927084%
HandleFriendRequestReceived(...)0%8.388081.82%
HandleSentFriendRequestApproved(...)0%3.013088.89%
ResetFadeOut(...)0%330100%
TogglePanelBackground(...)0%6200%
WaitThenFadeOutNotifications()0%10.378066.67%
ExtractPeerId(...)0%220100%
ResetVisibility(...)0%110100%
IsProfanityFilteringEnabled()0%110100%
HandleClickedFriendRequest(...)0%6.056088.89%
OpenChat(...)0%110100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/NotificationMessagesHUD/ChatNotificationController.cs

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using DCL.Helpers;
 3using DCL.Interface;
 4using DCL.ProfanityFiltering;
 5using DCL.Social.Friends;
 6using System;
 7using System.Collections.Generic;
 8using System.Threading;
 9using UnityEngine;
 10using Channel = DCL.Chat.Channels.Channel;
 11
 12namespace DCL.Chat.Notifications
 13{
 14    public class ChatNotificationController : IHUD
 15    {
 16        private const int FADEOUT_DELAY = 8000;
 17        private const string NEW_FRIEND_REQUESTS_FLAG = "new_friend_requests";
 18
 19        private readonly DataStore dataStore;
 20        private readonly IChatController chatController;
 21        private readonly IFriendsController friendsController;
 22        private readonly IMainChatNotificationsComponentView mainChatNotificationView;
 23        private readonly ITopNotificationsComponentView topNotificationView;
 24        private readonly IUserProfileBridge userProfileBridge;
 25        private readonly IProfanityFilter profanityFilter;
 1326        private readonly TimeSpan maxNotificationInterval = new (0, 1, 0);
 1327        private readonly HashSet<string> notificationEntries = new ();
 3928        private BaseVariable<bool> shouldShowNotificationPanel => dataStore.HUDs.shouldShowNotificationPanel;
 1329        private BaseVariable<Transform> notificationPanelTransform => dataStore.HUDs.notificationPanelTransform;
 4930        private BaseVariable<Transform> topNotificationPanelTransform => dataStore.HUDs.topNotificationPanelTransform;
 2631        private BaseVariable<HashSet<string>> visibleTaskbarPanels => dataStore.HUDs.visibleTaskbarPanels;
 732        private BaseVariable<string> openedChat => dataStore.HUDs.openedChat;
 1333        private CancellationTokenSource fadeOutCT = new ();
 34        private UserProfile internalOwnUserProfile;
 35        private UserProfile ownUserProfile
 36        {
 37            get
 38            {
 1939                internalOwnUserProfile ??= userProfileBridge.GetOwn();
 1940                return internalOwnUserProfile;
 41            }
 42        }
 343        private bool isNewFriendRequestsEnabled => dataStore.featureFlags.flags.Get().IsFeatureEnabled(NEW_FRIEND_REQUES
 44
 1345        public ChatNotificationController(DataStore dataStore,
 46            IMainChatNotificationsComponentView mainChatNotificationView,
 47            ITopNotificationsComponentView topNotificationView,
 48            IChatController chatController,
 49            IFriendsController friendsController,
 50            IUserProfileBridge userProfileBridge,
 51            IProfanityFilter profanityFilter)
 52        {
 1353            this.dataStore = dataStore;
 1354            this.chatController = chatController;
 1355            this.friendsController = friendsController;
 1356            this.userProfileBridge = userProfileBridge;
 1357            this.profanityFilter = profanityFilter;
 1358            this.mainChatNotificationView = mainChatNotificationView;
 1359            this.topNotificationView = topNotificationView;
 1360            mainChatNotificationView.OnResetFade += ResetFadeOut;
 1361            topNotificationView.OnResetFade += ResetFadeOut;
 1362            mainChatNotificationView.OnPanelFocus += TogglePanelBackground;
 1363            mainChatNotificationView.OnClickedFriendRequest += HandleClickedFriendRequest;
 1364            topNotificationView.OnClickedFriendRequest += HandleClickedFriendRequest;
 1365            mainChatNotificationView.OnClickedChatMessage += OpenChat;
 1366            topNotificationView.OnClickedChatMessage += OpenChat;
 1367            chatController.OnAddMessage += HandleMessageAdded;
 1368            friendsController.OnFriendRequestReceived += HandleFriendRequestReceived;
 1369            friendsController.OnSentFriendRequestApproved += HandleSentFriendRequestApproved;
 1370            notificationPanelTransform.Set(mainChatNotificationView.GetPanelTransform());
 1371            topNotificationPanelTransform.Set(topNotificationView.GetPanelTransform());
 1372            visibleTaskbarPanels.OnChange += VisiblePanelsChanged;
 1373            shouldShowNotificationPanel.OnChange += ResetVisibility;
 1374            ResetVisibility(shouldShowNotificationPanel.Get(), false);
 1375        }
 76
 77        public void SetVisibility(bool visible)
 78        {
 1379            ResetFadeOut(visible);
 80
 1381            if (visible)
 82            {
 1383                if (shouldShowNotificationPanel.Get())
 1384                    mainChatNotificationView.Show();
 85
 1386                topNotificationView.Hide();
 1387                mainChatNotificationView.ShowNotifications();
 88            }
 89            else
 90            {
 091                mainChatNotificationView.Hide();
 92
 093                if (!visibleTaskbarPanels.Get().Contains("WorldChatPanel"))
 094                    topNotificationView.Show();
 95            }
 096        }
 97
 98        public void Dispose()
 99        {
 13100            chatController.OnAddMessage -= HandleMessageAdded;
 13101            friendsController.OnFriendRequestReceived -= HandleFriendRequestReceived;
 13102            friendsController.OnSentFriendRequestApproved -= HandleSentFriendRequestApproved;
 13103            visibleTaskbarPanels.OnChange -= VisiblePanelsChanged;
 13104            mainChatNotificationView.OnResetFade -= ResetFadeOut;
 13105            topNotificationView.OnResetFade -= ResetFadeOut;
 13106            mainChatNotificationView.OnClickedChatMessage -= OpenChat;
 13107            topNotificationView.OnClickedChatMessage -= OpenChat;
 13108        }
 109
 110        private void VisiblePanelsChanged(HashSet<string> newList, HashSet<string> oldList)
 111        {
 0112            SetVisibility(newList.Count == 0);
 0113        }
 114
 115        private void HandleMessageAdded(ChatMessage[] messages)
 116        {
 31117            foreach (var message in messages)
 118            {
 8119                if (message.messageType != ChatMessage.Type.PRIVATE &&
 0120                    message.messageType != ChatMessage.Type.PUBLIC) return;
 121
 8122                if (message.sender == ownUserProfile.userId) return;
 123
 8124                var span = Utils.UnixToDateTimeWithTime((ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()) -
 125                           Utils.UnixToDateTimeWithTime(message.timestamp);
 126
 9127                if (span >= maxNotificationInterval) return;
 128
 7129                var channel = chatController.GetAllocatedChannel(
 130                    string.IsNullOrEmpty(message.recipient) && message.messageType == ChatMessage.Type.PUBLIC
 131                        ? "nearby"
 132                        : message.recipient);
 133
 7134                if (channel?.Muted ?? false) return;
 135
 136                // TODO: entries may have an inconsistent state. We should update the entry with new data
 7137                if (notificationEntries.Contains(message.messageId)) return;
 7138                notificationEntries.Add(message.messageId);
 139
 7140                AddNotification(message, channel).Forget();
 141            }
 7142        }
 143
 144        private async UniTaskVoid AddNotification(ChatMessage message, Channel channel = null)
 145        {
 7146            var peerId = ExtractPeerId(message);
 7147            var peerProfile = userProfileBridge.Get(peerId);
 7148            var peerName = peerProfile?.userName ?? peerId;
 7149            var peerProfilePicture = peerProfile?.face256SnapshotURL;
 7150            var body = message.body;
 151
 7152            switch (message.messageType)
 153            {
 154                case ChatMessage.Type.PRIVATE:
 2155                    var privateModel = new PrivateChatMessageNotificationModel(message.messageId,
 156                        message.sender, body, message.timestamp, peerName, peerProfilePicture);
 157
 2158                    if (message.sender != openedChat.Get())
 159                    {
 2160                        mainChatNotificationView.AddNewChatNotification(privateModel);
 161
 2162                        if (topNotificationPanelTransform.Get().gameObject.activeInHierarchy)
 2163                            topNotificationView.AddNewChatNotification(privateModel);
 164                    }
 165
 2166                    break;
 167                case ChatMessage.Type.PUBLIC:
 5168                    if (IsProfanityFilteringEnabled())
 169                    {
 2170                        peerName = await profanityFilter.Filter(peerProfile?.userName ?? peerId);
 2171                        body = await profanityFilter.Filter(message.body);
 172                    }
 173
 5174                    var publicModel = new PublicChannelMessageNotificationModel(message.messageId,
 175                        body, channel?.Name ?? message.recipient, channel?.ChannelId, message.timestamp,
 176                        peerName);
 177
 5178                    if (channel?.ChannelId != openedChat.Get())
 179                    {
 5180                        mainChatNotificationView.AddNewChatNotification(publicModel);
 181
 5182                        if (topNotificationPanelTransform.Get().gameObject.activeInHierarchy)
 5183                            topNotificationView.AddNewChatNotification(publicModel);
 184                    }
 185
 186                    break;
 187            }
 7188        }
 189
 190        private void HandleFriendRequestReceived(FriendRequest friendRequest)
 191        {
 2192            if (!isNewFriendRequestsEnabled) return;
 193
 2194            if (friendRequest.From == ownUserProfile.userId ||
 195                friendRequest.To != ownUserProfile.userId)
 0196                return;
 197
 2198            var friendRequestProfile = userProfileBridge.Get(friendRequest.From);
 2199            var friendRequestName = friendRequestProfile?.userName ?? friendRequest.From;
 200
 2201            FriendRequestNotificationModel friendRequestNotificationModel = new FriendRequestNotificationModel(
 202                friendRequest.FriendRequestId,
 203                friendRequest.From,
 204                friendRequestName,
 205                "Friend Request received",
 206                "wants to be your friend.",
 207                (ulong)friendRequest.Timestamp,
 208                false);
 209
 2210            mainChatNotificationView.AddNewFriendRequestNotification(friendRequestNotificationModel);
 211
 2212            if (topNotificationPanelTransform.Get().gameObject.activeInHierarchy)
 2213                topNotificationView.AddNewFriendRequestNotification(friendRequestNotificationModel);
 2214        }
 215
 216        private void HandleSentFriendRequestApproved(FriendRequest friendRequest)
 217        {
 1218            if (!isNewFriendRequestsEnabled) return;
 219
 1220            string recipientUserId = friendRequest.To;
 1221            var friendRequestProfile = userProfileBridge.Get(recipientUserId);
 222
 1223            FriendRequestNotificationModel friendRequestNotificationModel = new FriendRequestNotificationModel(
 224                friendRequest.FriendRequestId,
 225                recipientUserId,
 226                friendRequestProfile.userName,
 227                "Friend Request accepted",
 228                "and you are friends now!",
 229                (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
 230                true);
 231
 1232            mainChatNotificationView.AddNewFriendRequestNotification(friendRequestNotificationModel);
 233
 1234            if (topNotificationPanelTransform.Get().gameObject.activeInHierarchy)
 1235                topNotificationView.AddNewFriendRequestNotification(friendRequestNotificationModel);
 1236        }
 237
 238        private void ResetFadeOut(bool fadeOutAfterDelay = false)
 239        {
 13240            mainChatNotificationView.ShowNotifications();
 241
 13242            if (topNotificationPanelTransform.Get().gameObject.activeInHierarchy)
 13243                topNotificationView.ShowNotification();
 244
 13245            fadeOutCT.Cancel();
 13246            fadeOutCT = new CancellationTokenSource();
 247
 13248            if (fadeOutAfterDelay)
 13249                WaitThenFadeOutNotifications(fadeOutCT.Token).Forget();
 13250        }
 251
 252        private void TogglePanelBackground(bool isInFocus)
 253        {
 0254            if (isInFocus)
 0255                mainChatNotificationView.ShowPanel();
 256            else
 0257                mainChatNotificationView.HidePanel();
 0258        }
 259
 260        private async UniTaskVoid WaitThenFadeOutNotifications(CancellationToken cancellationToken)
 261        {
 39262            await UniTask.Delay(FADEOUT_DELAY, cancellationToken: cancellationToken);
 13263            await UniTask.SwitchToMainThread(cancellationToken);
 264
 13265            if (cancellationToken.IsCancellationRequested)
 0266                return;
 267
 13268            mainChatNotificationView.HideNotifications();
 269
 13270            if (topNotificationPanelTransform.Get() != null &&
 271                topNotificationPanelTransform.Get().gameObject.activeInHierarchy)
 0272                topNotificationView.HideNotification();
 13273        }
 274
 275        private string ExtractPeerId(ChatMessage message) =>
 7276            message.sender != ownUserProfile.userId ? message.sender : message.recipient;
 277
 278        private void ResetVisibility(bool current, bool previous) =>
 13279            SetVisibility(current);
 280
 281        private bool IsProfanityFilteringEnabled() =>
 5282            dataStore.settings.profanityChatFilteringEnabled.Get();
 283
 284        private void HandleClickedFriendRequest(string friendRequestId, string userId, bool isAcceptedFromPeer)
 285        {
 2286            if (string.IsNullOrEmpty(friendRequestId)) return;
 287
 2288            FriendRequest request = friendsController.GetAllocatedFriendRequest(friendRequestId);
 2289            bool isFriend = friendsController.IsFriend(userId);
 290
 2291            if (request != null && !isFriend && !isAcceptedFromPeer)
 1292                dataStore.HUDs.openReceivedFriendRequestDetail.Set(friendRequestId, true);
 1293            else if (isFriend)
 1294                OpenChat(userId);
 1295        }
 296
 297        private void OpenChat(string chatId) =>
 1298            dataStore.HUDs.openChat.Set(chatId, true);
 299    }
 300}