< 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:225
Uncovered lines:31
Coverable lines:256
Total lines:492
Line coverage:87.8% (225 of 256)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
FriendsHUDController(...)0%110100%
Initialize(...)0%440100%
Dispose()0%770100%
SetVisibility(...)0%7.347080.95%
HandleViewClosed()0%2100%
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 SocialFeaturesAnalytics;
 6using UnityEngine;
 7
 8public class FriendsHUDController : IHUD
 9{
 10    private const int LOAD_FRIENDS_ON_DEMAND_COUNT = 30;
 11    private const int MAX_SEARCHED_FRIENDS = 100;
 12
 4413    private readonly Dictionary<string, FriendEntryModel> friends = new Dictionary<string, FriendEntryModel>();
 4414    private readonly Dictionary<string, FriendEntryModel> onlineFriends = new Dictionary<string, FriendEntryModel>();
 15    private readonly DataStore dataStore;
 16    private readonly IFriendsController friendsController;
 17    private readonly IUserProfileBridge userProfileBridge;
 18    private readonly ISocialAnalytics socialAnalytics;
 19    private readonly IChatController chatController;
 20
 21    private UserProfile ownUserProfile;
 22    private bool searchingFriends;
 23    private int lastSkipForFriends;
 24    private int lastSkipForFriendRequests;
 25
 026    public IFriendsHUDComponentView View { get; private set; }
 27
 28    public event Action<string> OnPressWhisper;
 29    public event Action OnOpened;
 30    public event Action OnClosed;
 31
 4432    public FriendsHUDController(DataStore dataStore,
 33        IFriendsController friendsController,
 34        IUserProfileBridge userProfileBridge,
 35        ISocialAnalytics socialAnalytics,
 36        IChatController chatController)
 37    {
 4438        this.dataStore = dataStore;
 4439        this.friendsController = friendsController;
 4440        this.userProfileBridge = userProfileBridge;
 4441        this.socialAnalytics = socialAnalytics;
 4442        this.chatController = chatController;
 4443    }
 44
 45    public void Initialize(IFriendsHUDComponentView view = null)
 46    {
 4447        view ??= FriendsHUDComponentView.Create();
 4448        View = view;
 49
 4450        view.Initialize(chatController, friendsController, socialAnalytics);
 4451        view.RefreshFriendsTab();
 4452        view.OnFriendRequestApproved += HandleRequestAccepted;
 4453        view.OnCancelConfirmation += HandleRequestCancelled;
 4454        view.OnRejectConfirmation += HandleRequestRejected;
 4455        view.OnFriendRequestSent += HandleRequestSent;
 4456        view.OnWhisper += HandleOpenWhisperChat;
 4457        view.OnClose += HandleViewClosed;
 4458        view.OnRequireMoreFriends += DisplayMoreFriends;
 4459        view.OnRequireMoreFriendRequests += DisplayMoreFriendRequests;
 4460        view.OnSearchFriendsRequested += SearchFriends;
 4461        view.OnFriendListDisplayed += DisplayFriendsIfAnyIsLoaded;
 4462        view.OnRequestListDisplayed += DisplayFriendRequestsIfAnyIsLoaded;
 63
 4464        ownUserProfile = userProfileBridge.GetOwn();
 4465        ownUserProfile.OnUpdate -= HandleProfileUpdated;
 4466        ownUserProfile.OnUpdate += HandleProfileUpdated;
 67
 4468        if (friendsController != null)
 69        {
 4470            friendsController.OnUpdateFriendship += HandleFriendshipUpdated;
 4471            friendsController.OnUpdateUserStatus += HandleUserStatusUpdated;
 4472            friendsController.OnFriendNotFound += OnFriendNotFound;
 73
 4474            if (friendsController.IsInitialized)
 75            {
 276                view.HideLoadingSpinner();
 277            }
 78            else
 79            {
 4280                view.ShowLoadingSpinner();
 4281                friendsController.OnInitialized -= HandleFriendsInitialized;
 4282                friendsController.OnInitialized += HandleFriendsInitialized;
 83            }
 84        }
 85
 4486        ShowOrHideMoreFriendsToLoadHint();
 4487        ShowOrHideMoreFriendRequestsToLoadHint();
 4488    }
 89
 90    public void Dispose()
 91    {
 4592        if (friendsController != null)
 93        {
 4594            friendsController.OnInitialized -= HandleFriendsInitialized;
 4595            friendsController.OnUpdateFriendship -= HandleFriendshipUpdated;
 4596            friendsController.OnUpdateUserStatus -= HandleUserStatusUpdated;
 97        }
 98
 4599        if (View != null)
 100        {
 45101            View.OnFriendRequestApproved -= HandleRequestAccepted;
 45102            View.OnCancelConfirmation -= HandleRequestCancelled;
 45103            View.OnRejectConfirmation -= HandleRequestRejected;
 45104            View.OnFriendRequestSent -= HandleRequestSent;
 45105            View.OnWhisper -= HandleOpenWhisperChat;
 45106            View.OnDeleteConfirmation -= HandleUnfriend;
 45107            View.OnClose -= HandleViewClosed;
 45108            View.OnRequireMoreFriends -= DisplayMoreFriends;
 45109            View.OnRequireMoreFriendRequests -= DisplayMoreFriendRequests;
 45110            View.OnSearchFriendsRequested -= SearchFriends;
 45111            View.OnFriendListDisplayed -= DisplayFriendsIfAnyIsLoaded;
 45112            View.OnRequestListDisplayed -= DisplayFriendRequestsIfAnyIsLoaded;
 45113            View.Dispose();
 114        }
 115
 45116        if (ownUserProfile != null)
 45117            ownUserProfile.OnUpdate -= HandleProfileUpdated;
 118
 45119        if (userProfileBridge != null)
 120        {
 126121            foreach (var friendId in friends.Keys)
 122            {
 18123                var profile = userProfileBridge.Get(friendId);
 18124                if (profile == null) continue;
 16125                profile.OnUpdate -= HandleFriendProfileUpdated;
 126            }
 127        }
 45128    }
 129
 130    public void SetVisibility(bool visible)
 131    {
 18132        if (visible)
 133        {
 14134            lastSkipForFriends = 0;
 14135            lastSkipForFriendRequests = 0;
 14136            View.ClearAll();
 14137            View.Show();
 14138            UpdateNotificationsCounter();
 139
 28140            foreach (var friend in onlineFriends)
 0141                View.Set(friend.Key, friend.Value);
 142
 14143            if (View.IsFriendListActive)
 6144                DisplayMoreFriends();
 8145            else if (View.IsRequestListActive)
 5146                DisplayMoreFriendRequests();
 147
 14148            OnOpened?.Invoke();
 0149        }
 150        else
 151        {
 4152            View.Hide();
 4153            View.DisableSearchMode();
 4154            searchingFriends = false;
 4155            OnClosed?.Invoke();
 156        }
 0157    }
 158
 0159    private void HandleViewClosed() => SetVisibility(false);
 160
 161    private void HandleFriendsInitialized()
 162    {
 1163        friendsController.OnInitialized -= HandleFriendsInitialized;
 1164        View.HideLoadingSpinner();
 165
 1166        if (View.IsActive())
 167        {
 0168            if (View.IsFriendListActive && lastSkipForFriends <= 0)
 0169                DisplayMoreFriends();
 0170            else if (View.IsRequestListActive && lastSkipForFriendRequests <= 0)
 0171                DisplayMoreFriendRequests();
 172        }
 173
 1174        UpdateNotificationsCounter();
 1175    }
 176
 2177    private void HandleProfileUpdated(UserProfile profile) => UpdateBlockStatus(profile).Forget();
 178
 179    private async UniTask UpdateBlockStatus(UserProfile profile)
 180    {
 181        const int iterationsPerFrame = 10;
 182
 183        //NOTE(Brian): HashSet to check Contains quicker.
 2184        var allBlockedUsers = profile.blocked != null
 185            ? new HashSet<string>(profile.blocked)
 186            : new HashSet<string>();
 187
 2188        var iterations = 0;
 189
 8190        foreach (var friendPair in friends)
 191        {
 2192            var friendId = friendPair.Key;
 2193            var model = friendPair.Value;
 194
 2195            model.blocked = allBlockedUsers.Contains(friendId);
 2196            await UniTask.SwitchToMainThread();
 2197            View.UpdateBlockStatus(friendId, model.blocked);
 198
 2199            iterations++;
 2200            if (iterations > 0 && iterations % iterationsPerFrame == 0)
 0201                await UniTask.NextFrame();
 2202        }
 2203    }
 204
 205    private void HandleRequestSent(string userNameOrId)
 206    {
 3207        if (AreAlreadyFriends(userNameOrId))
 208        {
 1209            View.ShowRequestSendError(FriendRequestError.AlreadyFriends);
 1210        }
 211        else
 212        {
 2213            friendsController.RequestFriendship(userNameOrId);
 214
 2215            if (ownUserProfile != null)
 2216                socialAnalytics.SendFriendRequestSent(ownUserProfile.userId, userNameOrId, 0,
 217                    PlayerActionSource.FriendsHUD);
 218
 2219            View.ShowRequestSendSuccess();
 220        }
 2221    }
 222
 223    private bool AreAlreadyFriends(string userNameOrId)
 224    {
 3225        var userId = userNameOrId;
 3226        var profile = userProfileBridge.GetByName(userNameOrId);
 227
 3228        if (profile != default)
 1229            userId = profile.userId;
 230
 3231        return friendsController != null
 232               && friendsController.ContainsStatus(userId, FriendshipStatus.FRIEND);
 233    }
 234
 235    private void HandleUserStatusUpdated(string userId, UserStatus status) =>
 6236        UpdateUserStatus(userId, status);
 237
 238    private void UpdateUserStatus(string userId, UserStatus status)
 239    {
 7240        switch (status.friendshipStatus)
 241        {
 242            case FriendshipStatus.FRIEND:
 3243                var friend = friends.ContainsKey(userId)
 244                    ? new FriendEntryModel(friends[userId])
 245                    : new FriendEntryModel();
 3246                friend.CopyFrom(status);
 3247                friend.blocked = IsUserBlocked(userId);
 3248                friends[userId] = friend;
 3249                View.Set(userId, friend);
 250
 3251                if (status.presence == PresenceStatus.ONLINE)
 2252                    onlineFriends[userId] = friend;
 253                else
 1254                    onlineFriends.Remove(userId);
 255
 1256                break;
 257            case FriendshipStatus.NOT_FRIEND:
 0258                View.Remove(userId);
 0259                friends.Remove(userId);
 0260                onlineFriends.Remove(userId);
 0261                break;
 262            case FriendshipStatus.REQUESTED_TO:
 2263                var sentRequest = friends.ContainsKey(userId)
 264                    ? new FriendRequestEntryModel(friends[userId], false)
 265                    : new FriendRequestEntryModel {isReceived = false};
 2266                sentRequest.CopyFrom(status);
 2267                sentRequest.blocked = IsUserBlocked(userId);
 2268                friends[userId] = sentRequest;
 2269                onlineFriends.Remove(userId);
 2270                View.Set(userId, sentRequest);
 2271                break;
 272            case FriendshipStatus.REQUESTED_FROM:
 2273                var receivedRequest = friends.ContainsKey(userId)
 274                    ? new FriendRequestEntryModel(friends[userId], true)
 275                    : new FriendRequestEntryModel {isReceived = true};
 2276                receivedRequest.CopyFrom(status);
 2277                receivedRequest.blocked = IsUserBlocked(userId);
 2278                friends[userId] = receivedRequest;
 2279                onlineFriends.Remove(userId);
 2280                View.Set(userId, receivedRequest);
 281                break;
 282        }
 283
 7284        UpdateNotificationsCounter();
 7285        ShowOrHideMoreFriendsToLoadHint();
 7286        ShowOrHideMoreFriendRequestsToLoadHint();
 7287    }
 288
 289    private void HandleFriendshipUpdated(string userId, FriendshipAction friendshipAction)
 290    {
 15291        var userProfile = userProfileBridge.Get(userId);
 292
 15293        if (userProfile == null)
 294        {
 0295            Debug.LogError($"UserProfile is null for {userId}! ... friendshipAction {friendshipAction}");
 0296            return;
 297        }
 298
 15299        userProfile.OnUpdate -= HandleFriendProfileUpdated;
 300
 301        switch (friendshipAction)
 302        {
 303            case FriendshipAction.NONE:
 304            case FriendshipAction.REJECTED:
 305            case FriendshipAction.CANCELLED:
 306            case FriendshipAction.DELETED:
 3307                friends.Remove(userId);
 3308                View.Remove(userId);
 3309                onlineFriends.Remove(userId);
 3310                break;
 311            case FriendshipAction.APPROVED:
 7312                var approved = friends.ContainsKey(userId)
 313                    ? new FriendEntryModel(friends[userId])
 314                    : new FriendEntryModel();
 7315                approved.CopyFrom(userProfile);
 7316                approved.blocked = IsUserBlocked(userId);
 7317                friends[userId] = approved;
 7318                View.Set(userId, approved);
 7319                userProfile.OnUpdate += HandleFriendProfileUpdated;
 7320                break;
 321            case FriendshipAction.REQUESTED_FROM:
 2322                var requestReceived = friends.ContainsKey(userId)
 323                    ? new FriendRequestEntryModel(friends[userId], true)
 324                    : new FriendRequestEntryModel {isReceived = true};
 2325                requestReceived.CopyFrom(userProfile);
 2326                requestReceived.blocked = IsUserBlocked(userId);
 2327                friends[userId] = requestReceived;
 2328                View.Set(userId, requestReceived);
 2329                userProfile.OnUpdate += HandleFriendProfileUpdated;
 2330                break;
 331            case FriendshipAction.REQUESTED_TO:
 3332                var requestSent = friends.ContainsKey(userId)
 333                    ? new FriendRequestEntryModel(friends[userId], false)
 334                    : new FriendRequestEntryModel {isReceived = false};
 3335                requestSent.CopyFrom(userProfile);
 3336                requestSent.blocked = IsUserBlocked(userId);
 3337                friends[userId] = requestSent;
 3338                View.Set(userId, requestSent);
 3339                userProfile.OnUpdate += HandleFriendProfileUpdated;
 340                break;
 341        }
 342
 15343        UpdateNotificationsCounter();
 15344        ShowOrHideMoreFriendsToLoadHint();
 15345        ShowOrHideMoreFriendRequestsToLoadHint();
 15346    }
 347
 348    private void HandleFriendProfileUpdated(UserProfile profile)
 349    {
 1350        var userId = profile.userId;
 1351        if (!friends.ContainsKey(userId)) return;
 1352        friends[userId].CopyFrom(profile);
 353
 1354        var status = friendsController.GetUserStatus(profile.userId);
 1355        if (status == null) return;
 356
 1357        UpdateUserStatus(userId, status);
 1358    }
 359
 360    private bool IsUserBlocked(string userId)
 361    {
 19362        if (ownUserProfile != null && ownUserProfile.blocked != null)
 19363            return ownUserProfile.blocked.Contains(userId);
 0364        return false;
 365    }
 366
 367    private void OnFriendNotFound(string name)
 368    {
 1369        View.DisplayFriendUserNotFound();
 1370    }
 371
 372    private void UpdateNotificationsCounter()
 373    {
 37374        if (View.IsActive())
 9375            dataStore.friendNotifications.seenFriends.Set(View.FriendCount);
 376
 37377        dataStore.friendNotifications.pendingFriendRequestCount.Set(friendsController.ReceivedRequestCount);
 37378    }
 379
 1380    private void HandleOpenWhisperChat(FriendEntryModel entry) => OnPressWhisper?.Invoke(entry.userId);
 381
 0382    private void HandleUnfriend(string userId) => friendsController.RemoveFriend(userId);
 383
 384    private void HandleRequestRejected(FriendRequestEntryModel entry)
 385    {
 0386        friendsController.RejectFriendship(entry.userId);
 387
 0388        UpdateNotificationsCounter();
 389
 0390        if (ownUserProfile != null)
 0391            socialAnalytics.SendFriendRequestRejected(ownUserProfile.userId, entry.userId,
 392                PlayerActionSource.FriendsHUD);
 0393    }
 394
 395    private void HandleRequestCancelled(FriendRequestEntryModel entry)
 396    {
 0397        friendsController.CancelRequest(entry.userId);
 398
 0399        if (ownUserProfile != null)
 0400            socialAnalytics.SendFriendRequestCancelled(ownUserProfile.userId, entry.userId,
 401                PlayerActionSource.FriendsHUD);
 0402    }
 403
 404    private void HandleRequestAccepted(FriendRequestEntryModel entry)
 405    {
 0406        friendsController.AcceptFriendship(entry.userId);
 407
 0408        if (ownUserProfile != null)
 0409            socialAnalytics.SendFriendRequestApproved(ownUserProfile.userId, entry.userId,
 410                PlayerActionSource.FriendsHUD);
 0411    }
 412
 413    private void DisplayFriendsIfAnyIsLoaded()
 414    {
 1415        if (View.FriendCount > 0) return;
 1416        if (lastSkipForFriends > 0) return;
 1417        DisplayMoreFriends();
 1418    }
 419
 420    private void DisplayMoreFriends()
 421    {
 10422        if (!friendsController.IsInitialized) return;
 423
 8424        friendsController.GetFriends(LOAD_FRIENDS_ON_DEMAND_COUNT, lastSkipForFriends);
 425
 426        // We are not handling properly the case when the friends are not fetched correctly from server.
 427        // 'lastSkipForFriends' will have an invalid value.
 8428        lastSkipForFriends += LOAD_FRIENDS_ON_DEMAND_COUNT;
 429
 8430        ShowOrHideMoreFriendsToLoadHint();
 8431    }
 432
 433    private void DisplayMoreFriendRequests()
 434    {
 7435        if (!friendsController.IsInitialized) return;
 7436        if (searchingFriends) return;
 437
 7438        friendsController.GetFriendRequests(
 439            LOAD_FRIENDS_ON_DEMAND_COUNT, lastSkipForFriendRequests,
 440            LOAD_FRIENDS_ON_DEMAND_COUNT, lastSkipForFriendRequests);
 441
 442        // We are not handling properly the case when the friend requests are not fetched correctly from server.
 443        // 'lastSkipForFriendRequests' will have an invalid value.
 7444        lastSkipForFriendRequests += LOAD_FRIENDS_ON_DEMAND_COUNT;
 445
 7446        ShowOrHideMoreFriendRequestsToLoadHint();
 7447    }
 448
 449    private void DisplayFriendRequestsIfAnyIsLoaded()
 450    {
 1451        if (View.FriendRequestCount > 0) return;
 1452        if (lastSkipForFriendRequests > 0) return;
 1453        DisplayMoreFriendRequests();
 1454    }
 455
 456    private void ShowOrHideMoreFriendRequestsToLoadHint()
 457    {
 73458        if (lastSkipForFriendRequests >= friendsController.TotalFriendRequestCount)
 72459            View.HideMoreRequestsToLoadHint();
 460        else
 1461            View.ShowMoreRequestsToLoadHint(Mathf.Clamp(friendsController.TotalFriendRequestCount - lastSkipForFriendReq
 462                0,
 463                friendsController.TotalFriendRequestCount));
 1464    }
 465
 466    private void ShowOrHideMoreFriendsToLoadHint()
 467    {
 75468        if (lastSkipForFriends >= friendsController.TotalFriendCount || searchingFriends)
 74469            View.HideMoreFriendsToLoadHint();
 470        else
 1471            View.ShowMoreFriendsToLoadHint(Mathf.Clamp(friendsController.TotalFriendCount - lastSkipForFriends,
 472                0,
 473                friendsController.TotalFriendCount));
 1474    }
 475
 476    private void SearchFriends(string search)
 477    {
 3478        if (string.IsNullOrEmpty(search))
 479        {
 1480            View.DisableSearchMode();
 1481            searchingFriends = false;
 1482            ShowOrHideMoreFriendsToLoadHint();
 1483            return;
 484        }
 485
 2486        friendsController.GetFriends(search, MAX_SEARCHED_FRIENDS);
 487
 2488        View.EnableSearchMode();
 2489        View.HideMoreFriendsToLoadHint();
 2490        searchingFriends = true;
 2491    }
 492}