< Summary

Class:FriendsHUDController
Assembly:FriendsHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/FriendsHUD/Scripts/FriendsHUDController.cs
Covered lines:235
Uncovered lines:31
Coverable lines:266
Total lines:518
Line coverage:88.3% (235 of 266)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
FriendsHUDController(...)0%110100%
Initialize(...)0%550100%
SetVisiblePanelList(...)0%220100%
Dispose()0%770100%
SetVisibility(...)0%7.147085.71%
HandleViewClosed()0%6200%
HandleFriendsInitialized()0%9.166055.56%
HandleProfileUpdated(...)0%110100%
UpdateBlockStatus()0%13.2111073.68%
HandleRequestSent(...)0%330100%
AreAlreadyFriends(...)0%330100%
HandleUserStatusUpdated(...)0%110100%
UpdateUserStatus(...)0%9.179087.1%
HandleFriendshipUpdated(...)0%9.029093.94%
HandleFriendProfileUpdated(...)0%3.13077.78%
IsUserBlocked(...)0%3.333066.67%
OnFriendNotFound(...)0%110100%
UpdateNotificationsCounter()0%220100%
HandleOpenWhisperChat(...)0%220100%
HandleUnfriend(...)0%2100%
HandleRequestRejected(...)0%6200%
HandleRequestCancelled(...)0%6200%
HandleRequestAccepted(...)0%6200%
DisplayFriendsIfAnyIsLoaded()0%3.333066.67%
DisplayMoreFriends()0%220100%
DisplayMoreFriendRequests()0%3.143075%
DisplayFriendRequestsIfAnyIsLoaded()0%3.333066.67%
ShowOrHideMoreFriendRequestsToLoadHint()0%220100%
ShowOrHideMoreFriendsToLoadHint()0%330100%
SearchFriends(...)0%220100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/FriendsHUD/Scripts/FriendsHUDController.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using Cysharp.Threading.Tasks;
 4using DCL;
 5using DCl.Social.Friends;
 6using DCL.Social.Friends;
 7using SocialFeaturesAnalytics;
 8using UnityEngine;
 9
 10public class FriendsHUDController : IHUD
 11{
 12    private const int LOAD_FRIENDS_ON_DEMAND_COUNT = 30;
 13    private const int MAX_SEARCHED_FRIENDS = 100;
 14
 4515    private readonly Dictionary<string, FriendEntryModel> friends = new Dictionary<string, FriendEntryModel>();
 4516    private readonly Dictionary<string, FriendEntryModel> onlineFriends = new Dictionary<string, FriendEntryModel>();
 17    private readonly DataStore dataStore;
 18    private readonly IFriendsController friendsController;
 19    private readonly IUserProfileBridge userProfileBridge;
 20    private readonly ISocialAnalytics socialAnalytics;
 21    private readonly IChatController chatController;
 22    private readonly IMouseCatcher mouseCatcher;
 3823    private BaseVariable<HashSet<string>> visibleTaskbarPanels => dataStore.HUDs.visibleTaskbarPanels;
 24
 25    private UserProfile ownUserProfile;
 26    private bool searchingFriends;
 27    private int lastSkipForFriends;
 28    private int lastSkipForFriendRequests;
 29
 99730    public IFriendsHUDComponentView View { get; private set; }
 31
 32    public event Action<string> OnPressWhisper;
 33    public event Action OnOpened;
 34    public event Action OnClosed;
 35    public event Action OnViewClosed;
 36
 4537    public FriendsHUDController(DataStore dataStore,
 38        IFriendsController friendsController,
 39        IUserProfileBridge userProfileBridge,
 40        ISocialAnalytics socialAnalytics,
 41        IChatController chatController,
 42        IMouseCatcher mouseCatcher)
 43    {
 4544        this.dataStore = dataStore;
 4545        this.friendsController = friendsController;
 4546        this.userProfileBridge = userProfileBridge;
 4547        this.socialAnalytics = socialAnalytics;
 4548        this.chatController = chatController;
 4549        this.mouseCatcher = mouseCatcher;
 4550    }
 51
 52    public void Initialize(IFriendsHUDComponentView view = null)
 53    {
 4554        view ??= FriendsHUDComponentView.Create();
 4555        View = view;
 56
 4557        view.Initialize(chatController, friendsController, socialAnalytics);
 4558        view.RefreshFriendsTab();
 4559        view.OnFriendRequestApproved += HandleRequestAccepted;
 4560        view.OnCancelConfirmation += HandleRequestCancelled;
 4561        view.OnRejectConfirmation += HandleRequestRejected;
 4562        view.OnFriendRequestSent += HandleRequestSent;
 4563        view.OnWhisper += HandleOpenWhisperChat;
 4564        view.OnClose += HandleViewClosed;
 4565        view.OnRequireMoreFriends += DisplayMoreFriends;
 4566        view.OnRequireMoreFriendRequests += DisplayMoreFriendRequests;
 4567        view.OnSearchFriendsRequested += SearchFriends;
 4568        view.OnFriendListDisplayed += DisplayFriendsIfAnyIsLoaded;
 4569        view.OnRequestListDisplayed += DisplayFriendRequestsIfAnyIsLoaded;
 70
 4571        if(mouseCatcher != null)
 4572            mouseCatcher.OnMouseLock += HandleViewClosed;
 73
 4574        ownUserProfile = userProfileBridge.GetOwn();
 4575        ownUserProfile.OnUpdate -= HandleProfileUpdated;
 4576        ownUserProfile.OnUpdate += HandleProfileUpdated;
 77
 4578        if (friendsController != null)
 79        {
 4580            friendsController.OnUpdateFriendship += HandleFriendshipUpdated;
 4581            friendsController.OnUpdateUserStatus += HandleUserStatusUpdated;
 4582            friendsController.OnFriendNotFound += OnFriendNotFound;
 83
 4584            if (friendsController.IsInitialized)
 85            {
 286                view.HideLoadingSpinner();
 87            }
 88            else
 89            {
 4390                view.ShowLoadingSpinner();
 4391                friendsController.OnInitialized -= HandleFriendsInitialized;
 4392                friendsController.OnInitialized += HandleFriendsInitialized;
 93            }
 94        }
 95
 4596        ShowOrHideMoreFriendsToLoadHint();
 4597        ShowOrHideMoreFriendRequestsToLoadHint();
 4598    }
 99
 100    private void SetVisiblePanelList(bool visible)
 101    {
 19102        HashSet<string> newSet = visibleTaskbarPanels.Get();
 19103        if (visible)
 15104            newSet.Add("FriendsPanel");
 105        else
 4106            newSet.Remove("FriendsPanel");
 107
 19108        visibleTaskbarPanels.Set(newSet, true);
 19109    }
 110
 111    public void Dispose()
 112    {
 46113        if (friendsController != null)
 114        {
 46115            friendsController.OnInitialized -= HandleFriendsInitialized;
 46116            friendsController.OnUpdateFriendship -= HandleFriendshipUpdated;
 46117            friendsController.OnUpdateUserStatus -= HandleUserStatusUpdated;
 118        }
 119
 46120        if (View != null)
 121        {
 46122            View.OnFriendRequestApproved -= HandleRequestAccepted;
 46123            View.OnCancelConfirmation -= HandleRequestCancelled;
 46124            View.OnRejectConfirmation -= HandleRequestRejected;
 46125            View.OnFriendRequestSent -= HandleRequestSent;
 46126            View.OnWhisper -= HandleOpenWhisperChat;
 46127            View.OnDeleteConfirmation -= HandleUnfriend;
 46128            View.OnClose -= HandleViewClosed;
 46129            View.OnRequireMoreFriends -= DisplayMoreFriends;
 46130            View.OnRequireMoreFriendRequests -= DisplayMoreFriendRequests;
 46131            View.OnSearchFriendsRequested -= SearchFriends;
 46132            View.OnFriendListDisplayed -= DisplayFriendsIfAnyIsLoaded;
 46133            View.OnRequestListDisplayed -= DisplayFriendRequestsIfAnyIsLoaded;
 46134            View.Dispose();
 135        }
 136
 46137        if (ownUserProfile != null)
 46138            ownUserProfile.OnUpdate -= HandleProfileUpdated;
 139
 46140        if (userProfileBridge != null)
 141        {
 128142            foreach (var friendId in friends.Keys)
 143            {
 18144                var profile = userProfileBridge.Get(friendId);
 18145                if (profile == null) continue;
 16146                profile.OnUpdate -= HandleFriendProfileUpdated;
 147            }
 148        }
 46149    }
 150
 151    public void SetVisibility(bool visible)
 152    {
 19153        SetVisiblePanelList(visible);
 19154        if (visible)
 155        {
 15156            lastSkipForFriends = 0;
 15157            lastSkipForFriendRequests = 0;
 15158            View.ClearAll();
 15159            View.Show();
 15160            UpdateNotificationsCounter();
 161
 30162            foreach (var friend in onlineFriends)
 0163                View.Set(friend.Key, friend.Value);
 164
 15165            if (View.IsFriendListActive)
 7166                DisplayMoreFriends();
 8167            else if (View.IsRequestListActive)
 5168                DisplayMoreFriendRequests();
 169
 15170            OnOpened?.Invoke();
 171        }
 172        else
 173        {
 4174            View.Hide();
 4175            View.DisableSearchMode();
 4176            searchingFriends = false;
 4177            OnClosed?.Invoke();
 178        }
 0179    }
 180
 181    private void HandleViewClosed()
 182    {
 0183        OnViewClosed?.Invoke();
 0184        SetVisibility(false);
 0185    }
 186
 187    private void HandleFriendsInitialized()
 188    {
 1189        friendsController.OnInitialized -= HandleFriendsInitialized;
 1190        View.HideLoadingSpinner();
 191
 1192        if (View.IsActive())
 193        {
 0194            if (View.IsFriendListActive && lastSkipForFriends <= 0)
 0195                DisplayMoreFriends();
 0196            else if (View.IsRequestListActive && lastSkipForFriendRequests <= 0)
 0197                DisplayMoreFriendRequests();
 198        }
 199
 1200        UpdateNotificationsCounter();
 1201    }
 202
 2203    private void HandleProfileUpdated(UserProfile profile) => UpdateBlockStatus(profile).Forget();
 204
 205    private async UniTask UpdateBlockStatus(UserProfile profile)
 206    {
 207        const int iterationsPerFrame = 10;
 208
 209        //NOTE(Brian): HashSet to check Contains quicker.
 2210        var allBlockedUsers = profile.blocked != null
 211            ? new HashSet<string>(profile.blocked)
 212            : new HashSet<string>();
 213
 2214        var iterations = 0;
 215
 8216        foreach (var friendPair in friends)
 217        {
 2218            var friendId = friendPair.Key;
 2219            var model = friendPair.Value;
 220
 2221            model.blocked = allBlockedUsers.Contains(friendId);
 2222            await UniTask.SwitchToMainThread();
 2223            View.UpdateBlockStatus(friendId, model.blocked);
 224
 2225            iterations++;
 2226            if (iterations > 0 && iterations % iterationsPerFrame == 0)
 0227                await UniTask.NextFrame();
 2228        }
 2229    }
 230
 231    private void HandleRequestSent(string userNameOrId)
 232    {
 3233        if (AreAlreadyFriends(userNameOrId))
 234        {
 1235            View.ShowRequestSendError(FriendRequestError.AlreadyFriends);
 236        }
 237        else
 238        {
 2239            friendsController.RequestFriendship(userNameOrId);
 240
 2241            if (ownUserProfile != null)
 2242                socialAnalytics.SendFriendRequestSent(ownUserProfile.userId, userNameOrId, 0,
 243                    PlayerActionSource.FriendsHUD);
 244
 2245            View.ShowRequestSendSuccess();
 246        }
 2247    }
 248
 249    private bool AreAlreadyFriends(string userNameOrId)
 250    {
 3251        var userId = userNameOrId;
 3252        var profile = userProfileBridge.GetByName(userNameOrId);
 253
 3254        if (profile != default)
 1255            userId = profile.userId;
 256
 3257        return friendsController != null
 258               && friendsController.ContainsStatus(userId, FriendshipStatus.FRIEND);
 259    }
 260
 261    private void HandleUserStatusUpdated(string userId, UserStatus status) =>
 6262        UpdateUserStatus(userId, status);
 263
 264    private void UpdateUserStatus(string userId, UserStatus status)
 265    {
 7266        switch (status.friendshipStatus)
 267        {
 268            case FriendshipStatus.FRIEND:
 3269                var friend = friends.ContainsKey(userId)
 270                    ? new FriendEntryModel(friends[userId])
 271                    : new FriendEntryModel();
 3272                friend.CopyFrom(status);
 3273                friend.blocked = IsUserBlocked(userId);
 3274                friends[userId] = friend;
 3275                View.Set(userId, friend);
 276
 3277                if (status.presence == PresenceStatus.ONLINE)
 2278                    onlineFriends[userId] = friend;
 279                else
 1280                    onlineFriends.Remove(userId);
 281
 1282                break;
 283            case FriendshipStatus.NOT_FRIEND:
 0284                View.Remove(userId);
 0285                friends.Remove(userId);
 0286                onlineFriends.Remove(userId);
 0287                break;
 288            case FriendshipStatus.REQUESTED_TO:
 2289                var sentRequest = friends.ContainsKey(userId)
 290                    ? new FriendRequestEntryModel(friends[userId], false)
 291                    : new FriendRequestEntryModel {isReceived = false};
 2292                sentRequest.CopyFrom(status);
 2293                sentRequest.blocked = IsUserBlocked(userId);
 2294                friends[userId] = sentRequest;
 2295                onlineFriends.Remove(userId);
 2296                View.Set(userId, sentRequest);
 2297                break;
 298            case FriendshipStatus.REQUESTED_FROM:
 2299                var receivedRequest = friends.ContainsKey(userId)
 300                    ? new FriendRequestEntryModel(friends[userId], true)
 301                    : new FriendRequestEntryModel {isReceived = true};
 2302                receivedRequest.CopyFrom(status);
 2303                receivedRequest.blocked = IsUserBlocked(userId);
 2304                friends[userId] = receivedRequest;
 2305                onlineFriends.Remove(userId);
 2306                View.Set(userId, receivedRequest);
 307                break;
 308        }
 309
 7310        UpdateNotificationsCounter();
 7311        ShowOrHideMoreFriendsToLoadHint();
 7312        ShowOrHideMoreFriendRequestsToLoadHint();
 7313    }
 314
 315    private void HandleFriendshipUpdated(string userId, FriendshipAction friendshipAction)
 316    {
 15317        var userProfile = userProfileBridge.Get(userId);
 318
 15319        if (userProfile == null)
 320        {
 0321            Debug.LogError($"UserProfile is null for {userId}! ... friendshipAction {friendshipAction}");
 0322            return;
 323        }
 324
 15325        userProfile.OnUpdate -= HandleFriendProfileUpdated;
 326
 327        switch (friendshipAction)
 328        {
 329            case FriendshipAction.NONE:
 330            case FriendshipAction.REJECTED:
 331            case FriendshipAction.CANCELLED:
 332            case FriendshipAction.DELETED:
 3333                friends.Remove(userId);
 3334                View.Remove(userId);
 3335                onlineFriends.Remove(userId);
 3336                break;
 337            case FriendshipAction.APPROVED:
 7338                var approved = friends.ContainsKey(userId)
 339                    ? new FriendEntryModel(friends[userId])
 340                    : new FriendEntryModel();
 7341                approved.CopyFrom(userProfile);
 7342                approved.blocked = IsUserBlocked(userId);
 7343                friends[userId] = approved;
 7344                View.Set(userId, approved);
 7345                userProfile.OnUpdate += HandleFriendProfileUpdated;
 7346                break;
 347            case FriendshipAction.REQUESTED_FROM:
 2348                var requestReceived = friends.ContainsKey(userId)
 349                    ? new FriendRequestEntryModel(friends[userId], true)
 350                    : new FriendRequestEntryModel {isReceived = true};
 2351                requestReceived.CopyFrom(userProfile);
 2352                requestReceived.blocked = IsUserBlocked(userId);
 2353                friends[userId] = requestReceived;
 2354                View.Set(userId, requestReceived);
 2355                userProfile.OnUpdate += HandleFriendProfileUpdated;
 2356                break;
 357            case FriendshipAction.REQUESTED_TO:
 3358                var requestSent = friends.ContainsKey(userId)
 359                    ? new FriendRequestEntryModel(friends[userId], false)
 360                    : new FriendRequestEntryModel {isReceived = false};
 3361                requestSent.CopyFrom(userProfile);
 3362                requestSent.blocked = IsUserBlocked(userId);
 3363                friends[userId] = requestSent;
 3364                View.Set(userId, requestSent);
 3365                userProfile.OnUpdate += HandleFriendProfileUpdated;
 366                break;
 367        }
 368
 15369        UpdateNotificationsCounter();
 15370        ShowOrHideMoreFriendsToLoadHint();
 15371        ShowOrHideMoreFriendRequestsToLoadHint();
 15372    }
 373
 374    private void HandleFriendProfileUpdated(UserProfile profile)
 375    {
 1376        var userId = profile.userId;
 1377        if (!friends.ContainsKey(userId)) return;
 1378        friends[userId].CopyFrom(profile);
 379
 1380        var status = friendsController.GetUserStatus(profile.userId);
 1381        if (status == null) return;
 382
 1383        UpdateUserStatus(userId, status);
 1384    }
 385
 386    private bool IsUserBlocked(string userId)
 387    {
 19388        if (ownUserProfile != null && ownUserProfile.blocked != null)
 19389            return ownUserProfile.blocked.Contains(userId);
 0390        return false;
 391    }
 392
 393    private void OnFriendNotFound(string name)
 394    {
 1395        View.DisplayFriendUserNotFound();
 1396    }
 397
 398    private void UpdateNotificationsCounter()
 399    {
 38400        if (View.IsActive())
 9401            dataStore.friendNotifications.seenFriends.Set(View.FriendCount);
 402
 38403        dataStore.friendNotifications.pendingFriendRequestCount.Set(friendsController.ReceivedRequestCount);
 38404    }
 405
 1406    private void HandleOpenWhisperChat(FriendEntryModel entry) => OnPressWhisper?.Invoke(entry.userId);
 407
 0408    private void HandleUnfriend(string userId) => friendsController.RemoveFriend(userId);
 409
 410    private void HandleRequestRejected(FriendRequestEntryModel entry)
 411    {
 0412        friendsController.RejectFriendship(entry.userId);
 413
 0414        UpdateNotificationsCounter();
 415
 0416        if (ownUserProfile != null)
 0417            socialAnalytics.SendFriendRequestRejected(ownUserProfile.userId, entry.userId,
 418                PlayerActionSource.FriendsHUD);
 0419    }
 420
 421    private void HandleRequestCancelled(FriendRequestEntryModel entry)
 422    {
 0423        friendsController.CancelRequest(entry.userId);
 424
 0425        if (ownUserProfile != null)
 0426            socialAnalytics.SendFriendRequestCancelled(ownUserProfile.userId, entry.userId,
 427                PlayerActionSource.FriendsHUD);
 0428    }
 429
 430    private void HandleRequestAccepted(FriendRequestEntryModel entry)
 431    {
 0432        friendsController.AcceptFriendship(entry.userId);
 433
 0434        if (ownUserProfile != null)
 0435            socialAnalytics.SendFriendRequestApproved(ownUserProfile.userId, entry.userId,
 436                PlayerActionSource.FriendsHUD);
 0437    }
 438
 439    private void DisplayFriendsIfAnyIsLoaded()
 440    {
 1441        if (View.FriendCount > 0) return;
 1442        if (lastSkipForFriends > 0) return;
 1443        DisplayMoreFriends();
 1444    }
 445
 446    private void DisplayMoreFriends()
 447    {
 11448        if (!friendsController.IsInitialized) return;
 449
 9450        friendsController.GetFriends(LOAD_FRIENDS_ON_DEMAND_COUNT, lastSkipForFriends);
 451
 452        // We are not handling properly the case when the friends are not fetched correctly from server.
 453        // 'lastSkipForFriends' will have an invalid value.
 9454        lastSkipForFriends += LOAD_FRIENDS_ON_DEMAND_COUNT;
 455
 9456        ShowOrHideMoreFriendsToLoadHint();
 9457    }
 458
 459    private void DisplayMoreFriendRequests()
 460    {
 7461        if (!friendsController.IsInitialized) return;
 7462        if (searchingFriends) return;
 463
 7464        friendsController.GetFriendRequests(
 465            LOAD_FRIENDS_ON_DEMAND_COUNT, lastSkipForFriendRequests,
 466            LOAD_FRIENDS_ON_DEMAND_COUNT, lastSkipForFriendRequests);
 467
 468        // We are not handling properly the case when the friend requests are not fetched correctly from server.
 469        // 'lastSkipForFriendRequests' will have an invalid value.
 7470        lastSkipForFriendRequests += LOAD_FRIENDS_ON_DEMAND_COUNT;
 471
 7472        ShowOrHideMoreFriendRequestsToLoadHint();
 7473    }
 474
 475    private void DisplayFriendRequestsIfAnyIsLoaded()
 476    {
 1477        if (View.FriendRequestCount > 0) return;
 1478        if (lastSkipForFriendRequests > 0) return;
 1479        DisplayMoreFriendRequests();
 1480    }
 481
 482    private void ShowOrHideMoreFriendRequestsToLoadHint()
 483    {
 74484        if (lastSkipForFriendRequests >= friendsController.TotalFriendRequestCount)
 73485            View.HideMoreRequestsToLoadHint();
 486        else
 1487            View.ShowMoreRequestsToLoadHint(Mathf.Clamp(friendsController.TotalFriendRequestCount - lastSkipForFriendReq
 488                0,
 489                friendsController.TotalFriendRequestCount));
 1490    }
 491
 492    private void ShowOrHideMoreFriendsToLoadHint()
 493    {
 77494        if (lastSkipForFriends >= friendsController.TotalFriendCount || searchingFriends)
 76495            View.HideMoreFriendsToLoadHint();
 496        else
 1497            View.ShowMoreFriendsToLoadHint(Mathf.Clamp(friendsController.TotalFriendCount - lastSkipForFriends,
 498                0,
 499                friendsController.TotalFriendCount));
 1500    }
 501
 502    private void SearchFriends(string search)
 503    {
 3504        if (string.IsNullOrEmpty(search))
 505        {
 1506            View.DisableSearchMode();
 1507            searchingFriends = false;
 1508            ShowOrHideMoreFriendsToLoadHint();
 1509            return;
 510        }
 511
 2512        friendsController.GetFriends(search, MAX_SEARCHED_FRIENDS);
 513
 2514        View.EnableSearchMode();
 2515        View.HideMoreFriendsToLoadHint();
 2516        searchingFriends = true;
 2517    }
 518}